diff --git a/lib/krb5/keytab_file.c b/lib/krb5/keytab_file.c index e1dac856c..cc9296841 100644 --- a/lib/krb5/keytab_file.c +++ b/lib/krb5/keytab_file.c @@ -294,6 +294,7 @@ static krb5_error_code fkt_start_seq_get_int(krb5_context context, krb5_keytab id, int flags, + int exclusive, krb5_kt_cursor *c) { int8_t pvno, tag; @@ -307,16 +308,23 @@ fkt_start_seq_get_int(krb5_context context, strerror(ret)); return ret; } + ret = _krb5_xlock(context, c->fd, exclusive, d->filename); + if (ret) { + close(c->fd); + return ret; + } c->sp = krb5_storage_from_fd(c->fd); krb5_storage_set_eof_code(c->sp, KRB5_KT_END); ret = krb5_ret_int8(c->sp, &pvno); if(ret) { krb5_storage_free(c->sp); + _krb5_xunlock(c->fd); close(c->fd); return ret; } if(pvno != 5) { krb5_storage_free(c->sp); + _krb5_xunlock(c->fd); close(c->fd); krb5_clear_error_string (context); return KRB5_KEYTAB_BADVNO; @@ -324,6 +332,7 @@ fkt_start_seq_get_int(krb5_context context, ret = krb5_ret_int8(c->sp, &tag); if (ret) { krb5_storage_free(c->sp); + _krb5_xunlock(c->fd); close(c->fd); return ret; } @@ -337,7 +346,7 @@ fkt_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *c) { - return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, c); + return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c); } static krb5_error_code @@ -409,6 +418,7 @@ fkt_end_seq_get(krb5_context context, krb5_kt_cursor *cursor) { krb5_storage_free(cursor->sp); + _krb5_xunlock(cursor->fd); close(cursor->fd); return 0; } @@ -448,17 +458,25 @@ fkt_add_entry(krb5_context context, strerror(ret)); return ret; } + ret = _krb5_xlock(context, fd, 1, d->filename); + if (ret) { + close(fd); + return ret; + } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = fkt_setup_keytab(context, id, sp); if(ret) { - krb5_storage_free(sp); - close(fd); - return ret; + goto out; } storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; + ret = _krb5_xlock(context, fd, 1, d->filename); + if (ret) { + close(fd); + return ret; + } sp = krb5_storage_from_fd(fd); krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb5_ret_int8(sp, &pvno); @@ -469,28 +487,21 @@ fkt_add_entry(krb5_context context, if(ret) { krb5_set_error_string(context, "%s: keytab is corrupted: %s", d->filename, strerror(ret)); - krb5_storage_free(sp); - close(fd); - return ret; + goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { - krb5_storage_free(sp); - close(fd); - krb5_clear_error_string (context); ret = KRB5_KEYTAB_BADVNO; krb5_set_error_string(context, "%s: %s", d->filename, strerror(ret)); - return ret; + goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { krb5_set_error_string(context, "%s: reading tag: %s", d->filename, strerror(ret)); - krb5_storage_free(sp); - close(fd); - return ret; + goto out; } id->version = tag; storage_set_flags(context, sp, id->version); @@ -559,6 +570,7 @@ fkt_add_entry(krb5_context context, krb5_data_free(&keytab); out: krb5_storage_free(sp); + _krb5_xunlock(fd); close(fd); return ret; } @@ -574,7 +586,7 @@ fkt_remove_entry(krb5_context context, int found = 0; krb5_error_code ret; - ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, &cursor); + ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, 1, &cursor); if(ret != 0) goto out; /* return other error here? */ while(fkt_next_entry_int(context, id, &e, &cursor,