diff options
author | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2009-09-21 14:26:15 -0700 |
---|---|---|
committer | Nadezhda Ivanova <nadezhda.ivanova@postpath.com> | 2009-09-21 14:26:15 -0700 |
commit | 13b979b03d86f3ae43dc5fd539fa5d3f22f579a0 (patch) | |
tree | 40e15be25f6b975e7c5b91f00fdf6030726e25e7 | |
parent | 025590e7a4758e86e7942642971b92fc6bab7a8e (diff) | |
parent | 1afc7c453c1d5f7e761e46cdc69900305a149820 (diff) | |
download | samba-13b979b03d86f3ae43dc5fd539fa5d3f22f579a0.tar.gz samba-13b979b03d86f3ae43dc5fd539fa5d3f22f579a0.tar.bz2 samba-13b979b03d86f3ae43dc5fd539fa5d3f22f579a0.zip |
Merge branch 'master' of git://git.samba.org/samba
29 files changed, 839 insertions, 541 deletions
diff --git a/lib/async_req/async_sock.c b/lib/async_req/async_sock.c index f5a0dfde70..18adb42a0c 100644 --- a/lib/async_req/async_sock.c +++ b/lib/async_req/async_sock.c @@ -160,6 +160,10 @@ static void async_recv_handler(struct tevent_context *ev, /* retry */ return; } + if (state->received == 0) { + tevent_req_error(req, EPIPE); + return; + } if (state->received == -1) { tevent_req_error(req, errno); return; diff --git a/lib/tdb/tools/tdbtool.c b/lib/tdb/tools/tdbtool.c index c0814e11de..e469cebf65 100644 --- a/lib/tdb/tools/tdbtool.c +++ b/lib/tdb/tools/tdbtool.c @@ -40,6 +40,9 @@ static int disable_mmap; enum commands { CMD_CREATE_TDB, CMD_OPEN_TDB, + CMD_TRANSACTION_START, + CMD_TRANSACTION_COMMIT, + CMD_TRANSACTION_CANCEL, CMD_ERASE, CMD_DUMP, CMD_INSERT, @@ -70,6 +73,9 @@ typedef struct { COMMAND_TABLE cmd_table[] = { {"create", CMD_CREATE_TDB}, {"open", CMD_OPEN_TDB}, + {"transaction_start", CMD_TRANSACTION_START}, + {"transaction_commit", CMD_TRANSACTION_COMMIT}, + {"transaction_cancel", CMD_TRANSACTION_CANCEL}, {"erase", CMD_ERASE}, {"dump", CMD_DUMP}, {"insert", CMD_INSERT}, @@ -169,6 +175,9 @@ static void help(void) "tdbtool: \n" " create dbname : create a database\n" " open dbname : open an existing database\n" +" transaction_start : start a transaction\n" +" transaction_commit : commit a transaction\n" +" transaction_cancel : cancel a transaction\n" " erase : erase the database\n" " dump : dump the database as strings\n" " keys : dump the database keys as strings\n" @@ -182,6 +191,7 @@ static void help(void) " list : print the database hash table and freelist\n" " free : print the database freelist\n" " check : check the integrity of an opened database\n" +" speed : perform speed tests on the database\n" " ! command : execute system command\n" " 1 | first : print the first record\n" " n | next : print the next record\n" @@ -536,117 +546,129 @@ static int do_command(void) int cmd_len; if (cmdname && strlen(cmdname) == 0) { - mycmd = CMD_NEXT; + mycmd = CMD_NEXT; } else { - while (ctp->name) { - cmd_len = strlen(ctp->name); - if (strncmp(ctp->name,cmdname,cmd_len) == 0) { - mycmd = ctp->cmd; - break; + while (ctp->name) { + cmd_len = strlen(ctp->name); + if (strncmp(ctp->name,cmdname,cmd_len) == 0) { + mycmd = ctp->cmd; + break; + } + ctp++; } - ctp++; - } } switch (mycmd) { case CMD_CREATE_TDB: - bIterate = 0; - create_tdb(arg1); - return 0; - case CMD_OPEN_TDB: - bIterate = 0; - open_tdb(arg1); - return 0; - case CMD_SYSTEM: - /* Shell command */ - if (system(arg1) == -1) { - terror("system() call failed\n"); - } - return 0; - case CMD_QUIT: - return 1; - default: - /* all the rest require a open database */ - if (!tdb) { - bIterate = 0; - terror("database not open"); - help(); - return 0; - } - switch (mycmd) { - case CMD_ERASE: - bIterate = 0; - tdb_traverse(tdb, do_delete_fn, NULL); - return 0; - case CMD_DUMP: - bIterate = 0; - tdb_traverse(tdb, print_rec, NULL); - return 0; - case CMD_INSERT: bIterate = 0; - insert_tdb(arg1, arg1len,arg2,arg2len); + create_tdb(arg1); return 0; - case CMD_MOVE: - bIterate = 0; - move_rec(arg1,arg1len,arg2); - return 0; - case CMD_STORE: - bIterate = 0; - store_tdb(arg1,arg1len,arg2,arg2len); - return 0; - case CMD_SHOW: - bIterate = 0; - show_tdb(arg1, arg1len); - return 0; - case CMD_KEYS: - tdb_traverse(tdb, print_key, NULL); - return 0; - case CMD_HEXKEYS: - tdb_traverse(tdb, print_hexkey, NULL); - return 0; - case CMD_DELETE: + case CMD_OPEN_TDB: bIterate = 0; - delete_tdb(arg1,arg1len); - return 0; - case CMD_LIST_HASH_FREE: - tdb_dump_all(tdb); + open_tdb(arg1); return 0; - case CMD_LIST_FREE: - tdb_printfreelist(tdb); - return 0; - case CMD_INFO: - info_tdb(); - return 0; - case CMD_SPEED: - speed_tdb(arg1); - return 0; - case CMD_MMAP: - toggle_mmap(); - return 0; - case CMD_FIRST: - bIterate = 1; - first_record(tdb, &iterate_kbuf); - return 0; - case CMD_NEXT: - if (bIterate) - next_record(tdb, &iterate_kbuf); - return 0; - case CMD_CHECK: - check_db(tdb); - return 0; - case CMD_HELP: - help(); + case CMD_SYSTEM: + /* Shell command */ + if (system(arg1) == -1) { + terror("system() call failed\n"); + } return 0; - case CMD_CREATE_TDB: - case CMD_OPEN_TDB: - case CMD_SYSTEM: - case CMD_QUIT: - /* - * unhandled commands. cases included here to avoid compiler - * warnings. - */ - return 0; - } + case CMD_QUIT: + return 1; + default: + /* all the rest require a open database */ + if (!tdb) { + bIterate = 0; + terror("database not open"); + help(); + return 0; + } + switch (mycmd) { + case CMD_TRANSACTION_START: + bIterate = 0; + tdb_transaction_start(tdb); + return 0; + case CMD_TRANSACTION_COMMIT: + bIterate = 0; + tdb_transaction_commit(tdb); + return 0; + case CMD_TRANSACTION_CANCEL: + bIterate = 0; + tdb_transaction_cancel(tdb); + return 0; + case CMD_ERASE: + bIterate = 0; + tdb_traverse(tdb, do_delete_fn, NULL); + return 0; + case CMD_DUMP: + bIterate = 0; + tdb_traverse(tdb, print_rec, NULL); + return 0; + case CMD_INSERT: + bIterate = 0; + insert_tdb(arg1, arg1len,arg2,arg2len); + return 0; + case CMD_MOVE: + bIterate = 0; + move_rec(arg1,arg1len,arg2); + return 0; + case CMD_STORE: + bIterate = 0; + store_tdb(arg1,arg1len,arg2,arg2len); + return 0; + case CMD_SHOW: + bIterate = 0; + show_tdb(arg1, arg1len); + return 0; + case CMD_KEYS: + tdb_traverse(tdb, print_key, NULL); + return 0; + case CMD_HEXKEYS: + tdb_traverse(tdb, print_hexkey, NULL); + return 0; + case CMD_DELETE: + bIterate = 0; + delete_tdb(arg1,arg1len); + return 0; + case CMD_LIST_HASH_FREE: + tdb_dump_all(tdb); + return 0; + case CMD_LIST_FREE: + tdb_printfreelist(tdb); + return 0; + case CMD_INFO: + info_tdb(); + return 0; + case CMD_SPEED: + speed_tdb(arg1); + return 0; + case CMD_MMAP: + toggle_mmap(); + return 0; + case CMD_FIRST: + bIterate = 1; + first_record(tdb, &iterate_kbuf); + return 0; + case CMD_NEXT: + if (bIterate) + next_record(tdb, &iterate_kbuf); + return 0; + case CMD_CHECK: + check_db(tdb); + return 0; + case CMD_HELP: + help(); + return 0; + case CMD_CREATE_TDB: + case CMD_OPEN_TDB: + case CMD_SYSTEM: + case CMD_QUIT: + /* + * unhandled commands. cases included here to avoid compiler + * warnings. + */ + return 0; + } } return 0; @@ -654,88 +676,87 @@ static int do_command(void) static char *convert_string(char *instring, size_t *sizep) { - size_t length = 0; - char *outp, *inp; - char temp[3]; - - - outp = inp = instring; - - while (*inp) { - if (*inp == '\\') { - inp++; - if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { - temp[0] = *inp++; - temp[1] = '\0'; - if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { - temp[1] = *inp++; - temp[2] = '\0'; + size_t length = 0; + char *outp, *inp; + char temp[3]; + + outp = inp = instring; + + while (*inp) { + if (*inp == '\\') { + inp++; + if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { + temp[0] = *inp++; + temp[1] = '\0'; + if (*inp && strchr("0123456789abcdefABCDEF",(int)*inp)) { + temp[1] = *inp++; + temp[2] = '\0'; + } + *outp++ = (char)strtol((const char *)temp,NULL,16); + } else { + *outp++ = *inp++; + } + } else { + *outp++ = *inp++; } - *outp++ = (char)strtol((const char *)temp,NULL,16); - } else { - *outp++ = *inp++; - } - } else { - *outp++ = *inp++; + length++; } - length++; - } - *sizep = length; - return instring; + *sizep = length; + return instring; } int main(int argc, char *argv[]) { - cmdname = ""; - arg1 = NULL; - arg1len = 0; - arg2 = NULL; - arg2len = 0; - - if (argv[1]) { - cmdname = "open"; - arg1 = argv[1]; - do_command(); - cmdname = ""; + cmdname = ""; arg1 = NULL; - } + arg1len = 0; + arg2 = NULL; + arg2len = 0; + + if (argv[1]) { + cmdname = "open"; + arg1 = argv[1]; + do_command(); + cmdname = ""; + arg1 = NULL; + } - switch (argc) { + switch (argc) { case 1: case 2: - /* Interactive mode */ - while ((cmdname = tdb_getline("tdb> "))) { - arg2 = arg1 = NULL; - if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) { - arg1++; - arg2 = arg1; - while (*arg2) { - if (*arg2 == ' ') { - *arg2++ = '\0'; - break; - } - if ((*arg2++ == '\\') && (*arg2 == ' ')) { - arg2++; + /* Interactive mode */ + while ((cmdname = tdb_getline("tdb> "))) { + arg2 = arg1 = NULL; + if ((arg1 = strchr((const char *)cmdname,' ')) != NULL) { + arg1++; + arg2 = arg1; + while (*arg2) { + if (*arg2 == ' ') { + *arg2++ = '\0'; + break; + } + if ((*arg2++ == '\\') && (*arg2 == ' ')) { + arg2++; + } + } } - } + if (arg1) arg1 = convert_string(arg1,&arg1len); + if (arg2) arg2 = convert_string(arg2,&arg2len); + if (do_command()) break; } - if (arg1) arg1 = convert_string(arg1,&arg1len); - if (arg2) arg2 = convert_string(arg2,&arg2len); - if (do_command()) break; - } - break; + break; case 5: - arg2 = convert_string(argv[4],&arg2len); + arg2 = convert_string(argv[4],&arg2len); case 4: - arg1 = convert_string(argv[3],&arg1len); + arg1 = convert_string(argv[3],&arg1len); case 3: - cmdname = argv[2]; + cmdname = argv[2]; default: - do_command(); - break; - } + do_command(); + break; + } - if (tdb) tdb_close(tdb); + if (tdb) tdb_close(tdb); - return 0; + return 0; } diff --git a/lib/tevent/tevent_signal.c b/lib/tevent/tevent_signal.c index ef9c0cf288..0ca2a2760b 100644 --- a/lib/tevent/tevent_signal.c +++ b/lib/tevent/tevent_signal.c @@ -85,6 +85,7 @@ static void tevent_common_signal_handler(int signum) ssize_t res; struct tevent_common_signal_list *sl; struct tevent_context *ev = NULL; + int saved_errno = errno; SIG_INCREMENT(sig_state->signal_count[signum]); SIG_INCREMENT(sig_state->got_signal); @@ -103,6 +104,8 @@ static void tevent_common_signal_handler(int signum) ev = sl->se->event_ctx; } } + + errno = saved_errno; } #ifdef SA_SIGINFO diff --git a/source3/lib/select.c b/source3/lib/select.c index a58530af8d..b5443ff20c 100644 --- a/source3/lib/select.c +++ b/source3/lib/select.c @@ -39,11 +39,15 @@ static volatile unsigned pipe_written, pipe_read; void sys_select_signal(char c) { + int saved_errno = errno; + if (!initialised) return; if (pipe_written > pipe_read+256) return; if (write(select_pipe[1], &c, 1) == 1) pipe_written++; + + errno = saved_errno; } /******************************************************************* diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 0e66e3cf01..36f401bc92 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -1135,8 +1135,8 @@ void secrets_fetch_ipc_userpass(char **username, char **domain, char **password) *******************************************************************************/ #define SCHANNEL_STORE_VERSION_1 1 -#define SCHANNEL_STORE_VERSION_2 2 -#define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_2 +#define SCHANNEL_STORE_VERSION_2 2 /* should not be used */ +#define SCHANNEL_STORE_VERSION_CURRENT SCHANNEL_STORE_VERSION_1 TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx) { @@ -1168,12 +1168,18 @@ TDB_CONTEXT *open_schannel_session_store(TALLOC_CTX *mem_ctx) vers.dptr = NULL; } else if (vers.dsize == 4) { ver = IVAL(vers.dptr,0); - if (ver != SCHANNEL_STORE_VERSION_CURRENT) { + if (ver == SCHANNEL_STORE_VERSION_2) { DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n", (int)ver, fname )); tdb_wipe_all(tdb_sc); goto again; } + if (ver != SCHANNEL_STORE_VERSION_CURRENT) { + DEBUG(0,("open_schannel_session_store: wrong version number %d in %s\n", + (int)ver, fname )); + tdb_close(tdb_sc); + tdb_sc = NULL; + } } else { tdb_close(tdb_sc); tdb_sc = NULL; diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 9d4676f9b5..f0160fcb78 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -692,6 +692,8 @@ static void winbind_client_response_written(struct tevent_req *req) ret = wb_resp_write_recv(req, &err); TALLOC_FREE(req); if (ret == -1) { + close(state->sock); + state->sock = -1; DEBUG(2, ("Could not write response to client: %s\n", strerror(err))); remove_client(state); @@ -792,6 +794,8 @@ static void winbind_client_request_read(struct tevent_req *req) ret = wb_req_read_recv(req, state, &state->request, &err); TALLOC_FREE(req); if (ret == -1) { + close(state->sock); + state->sock = -1; DEBUG(2, ("Could not read client request: %s\n", strerror(err))); remove_client(state); @@ -813,22 +817,19 @@ static void remove_client(struct winbindd_cli_state *state) return; } - /* tell client, we are closing ... */ - nwritten = write(state->sock, &c, sizeof(c)); - if (nwritten == -1) { - /* - * ignore EPIPE error here, because the other end might - * have already closed the socket. - */ - if (errno != EPIPE) { + if (state->sock != -1) { + /* tell client, we are closing ... */ + nwritten = write(state->sock, &c, sizeof(c)); + if (nwritten == -1) { DEBUG(2, ("final write to client failed: %s\n", - strerror(errno))); + strerror(errno))); } - } - /* Close socket */ + /* Close socket */ - close(state->sock); + close(state->sock); + state->sock = -1; + } /* Free any getent state */ diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c index a04e52469d..a50e5b4a66 100644 --- a/source4/dsdb/samdb/ldb_modules/password_hash.c +++ b/source4/dsdb/samdb/ldb_modules/password_hash.c @@ -248,7 +248,7 @@ static int setup_kerberos_keys(struct setup_password_fields_io *io) char *name; char *saltbody; - name = talloc_strdup(io->ac, io->u.sAMAccountName); + name = strlower_talloc(io->ac, io->u.sAMAccountName); if (!name) { ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; diff --git a/source4/dsdb/samdb/ldb_modules/resolve_oids.c b/source4/dsdb/samdb/ldb_modules/resolve_oids.c index f4d9eba17a..053c2ec55f 100644 --- a/source4/dsdb/samdb/ldb_modules/resolve_oids.c +++ b/source4/dsdb/samdb/ldb_modules/resolve_oids.c @@ -21,6 +21,199 @@ #include "ldb_module.h" #include "dsdb/samdb/samdb.h" +static int resolve_oids_need_value(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct dsdb_attribute *a, + const struct ldb_val *valp) +{ + const struct dsdb_attribute *va = NULL; + const struct dsdb_class *vo = NULL; + const void *p2; + char *str = NULL; + + if (a->syntax->oMSyntax != 6) { + return LDB_ERR_COMPARE_FALSE; + } + + if (valp) { + p2 = memchr(valp->data, '.', valp->length); + } else { + p2 = NULL; + } + + if (!p2) { + return LDB_ERR_COMPARE_FALSE; + } + + switch (a->attributeID_id) { + case DRSUAPI_ATTRIBUTE_objectClass: + case DRSUAPI_ATTRIBUTE_subClassOf: + case DRSUAPI_ATTRIBUTE_auxiliaryClass: + case DRSUAPI_ATTRIBUTE_systemPossSuperiors: + case DRSUAPI_ATTRIBUTE_possSuperiors: + str = talloc_strndup(ldb, (char *)valp->data, valp->length); + if (!str) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + vo = dsdb_class_by_governsID_oid(schema, str); + talloc_free(str); + if (!vo) { + return LDB_ERR_COMPARE_FALSE; + } + return LDB_ERR_COMPARE_TRUE; + case DRSUAPI_ATTRIBUTE_systemMustContain: + case DRSUAPI_ATTRIBUTE_systemMayContain: + case DRSUAPI_ATTRIBUTE_mustContain: + case DRSUAPI_ATTRIBUTE_mayContain: + str = talloc_strndup(ldb, (char *)valp->data, valp->length); + if (!str) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + va = dsdb_attribute_by_attributeID_oid(schema, str); + talloc_free(str); + if (!va) { + return LDB_ERR_COMPARE_FALSE; + } + return LDB_ERR_COMPARE_TRUE; + case DRSUAPI_ATTRIBUTE_governsID: + case DRSUAPI_ATTRIBUTE_attributeID: + case DRSUAPI_ATTRIBUTE_attributeSyntax: + return LDB_ERR_COMPARE_FALSE; + } + + return LDB_ERR_COMPARE_FALSE; +} + +static int resolve_oids_parse_tree_need(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct ldb_parse_tree *tree) +{ + int i; + const struct dsdb_attribute *a = NULL; + const char *attr; + const char *p1; + const void *p2; + const struct ldb_val *valp = NULL; + int ret; + + switch (tree->operation) { + case LDB_OP_AND: + case LDB_OP_OR: + for (i=0;i<tree->u.list.num_elements;i++) { + ret = resolve_oids_parse_tree_need(ldb, schema, + tree->u.list.elements[i]); + if (ret != LDB_ERR_COMPARE_FALSE) { + return ret; + } + } + return LDB_ERR_COMPARE_FALSE; + case LDB_OP_NOT: + return resolve_oids_parse_tree_need(ldb, schema, + tree->u.isnot.child); + case LDB_OP_EQUALITY: + case LDB_OP_GREATER: + case LDB_OP_LESS: + case LDB_OP_APPROX: + attr = tree->u.equality.attr; + valp = &tree->u.equality.value; + break; + case LDB_OP_SUBSTRING: + attr = tree->u.substring.attr; + break; + case LDB_OP_PRESENT: + attr = tree->u.present.attr; + break; + case LDB_OP_EXTENDED: + attr = tree->u.extended.attr; + valp = &tree->u.extended.value; + break; + default: + return LDB_ERR_COMPARE_FALSE; + } + + p1 = strchr(attr, '.'); + + if (valp) { + p2 = memchr(valp->data, '.', valp->length); + } else { + p2 = NULL; + } + + if (!p1 && !p2) { + return LDB_ERR_COMPARE_FALSE; + } + + if (p1) { + a = dsdb_attribute_by_attributeID_oid(schema, attr); + } else { + a = dsdb_attribute_by_lDAPDisplayName(schema, attr); + } + if (!a) { + return LDB_ERR_COMPARE_FALSE; + } + + if (!p2) { + return LDB_ERR_COMPARE_FALSE; + } + + if (a->syntax->oMSyntax != 6) { + return LDB_ERR_COMPARE_FALSE; + } + + return resolve_oids_need_value(ldb, schema, a, valp); +} + +static int resolve_oids_element_need(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct ldb_message_element *el) +{ + int i; + const struct dsdb_attribute *a = NULL; + const char *p1; + + p1 = strchr(el->name, '.'); + + if (p1) { + a = dsdb_attribute_by_attributeID_oid(schema, el->name); + } else { + a = dsdb_attribute_by_lDAPDisplayName(schema, el->name); + } + if (!a) { + return LDB_ERR_COMPARE_FALSE; + } + + for (i=0; i < el->num_values; i++) { + int ret; + ret = resolve_oids_need_value(ldb, schema, a, + &el->values[i]); + if (ret != LDB_ERR_COMPARE_FALSE) { + return ret; + } + } + + return LDB_ERR_COMPARE_FALSE; +} + +static int resolve_oids_message_need(struct ldb_context *ldb, + struct dsdb_schema *schema, + const struct ldb_message *msg) +{ + int i; + + for (i=0; i < msg->num_elements; i++) { + int ret; + ret = resolve_oids_element_need(ldb, schema, + &msg->elements[i]); + if (ret != LDB_ERR_COMPARE_FALSE) { + return ret; + } + } + + return LDB_ERR_COMPARE_FALSE; +} + static int resolve_oids_replace_value(struct ldb_context *ldb, struct dsdb_schema *schema, const struct dsdb_attribute *a, @@ -98,19 +291,22 @@ static int resolve_oids_parse_tree_replace(struct ldb_context *ldb, const char *p1; const void *p2; struct ldb_val *valp = NULL; + int ret; switch (tree->operation) { case LDB_OP_AND: case LDB_OP_OR: for (i=0;i<tree->u.list.num_elements;i++) { - resolve_oids_parse_tree_replace(ldb, schema, + ret = resolve_oids_parse_tree_replace(ldb, schema, tree->u.list.elements[i]); + if (ret != LDB_SUCCESS) { + return ret; + } } return LDB_SUCCESS; case LDB_OP_NOT: - resolve_oids_parse_tree_replace(ldb, schema, + return resolve_oids_parse_tree_replace(ldb, schema, tree->u.isnot.child); - return LDB_SUCCESS; case LDB_OP_EQUALITY: case LDB_OP_GREATER: case LDB_OP_LESS: @@ -275,6 +471,14 @@ static int resolve_oids_search(struct ldb_module *module, struct ldb_request *re return ldb_next_request(module, req); } + ret = resolve_oids_parse_tree_need(ldb, schema, + req->op.search.tree); + if (ret == LDB_ERR_COMPARE_FALSE) { + return ldb_next_request(module, req); + } else if (ret != LDB_ERR_COMPARE_TRUE) { + return ret; + } + ac = talloc(req, struct resolve_oids_context); if (ac == NULL) { ldb_oom(ldb); @@ -332,6 +536,14 @@ static int resolve_oids_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + ret = resolve_oids_message_need(ldb, schema, + req->op.add.message); + if (ret == LDB_ERR_COMPARE_FALSE) { + return ldb_next_request(module, req); + } else if (ret != LDB_ERR_COMPARE_TRUE) { + return ret; + } + ac = talloc(req, struct resolve_oids_context); if (ac == NULL) { ldb_oom(ldb); @@ -385,6 +597,14 @@ static int resolve_oids_modify(struct ldb_module *module, struct ldb_request *re return ldb_next_request(module, req); } + ret = resolve_oids_message_need(ldb, schema, + req->op.mod.message); + if (ret == LDB_ERR_COMPARE_FALSE) { + return ldb_next_request(module, req); + } else if (ret != LDB_ERR_COMPARE_TRUE) { + return ret; + } + ac = talloc(req, struct resolve_oids_context); if (ac == NULL) { ldb_oom(ldb); diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 613451a7c2..b75d837674 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -41,8 +41,8 @@ static int ldb_context_destructor(void *ptr) if (ldb->transaction_active) { ldb_debug(ldb, LDB_DEBUG_FATAL, - "A transaction is still active in ldb context [%p]", - ldb); + "A transaction is still active in ldb context [%p] on %s", + ldb, (const char *)ldb_get_opaque(ldb, "ldb_url")); } return 0; diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c index c4e786c833..70dee9597b 100644 --- a/source4/libnet/libnet_become_dc.c +++ b/source4/libnet/libnet_become_dc.c @@ -2101,7 +2101,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s) vd[0] = data_blob_talloc(vd, NULL, 4); if (composite_nomem(vd[0].data, c)) return; - SIVAL(vd[0].data, 0, DS_DC_FUNCTION_2008_R2); + SIVAL(vd[0].data, 0, DS_DC_FUNCTION_2008); vs[0].blob = &vd[0]; diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index 86ad685c51..fc7de10506 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -33,6 +33,7 @@ #include "auth/credentials/credentials_krb5.h" #include "librpc/gen_ndr/ndr_samr_c.h" #include "param/param.h" +#include "param/provision.h" /* * complete a domain join, when joining to a AD domain: @@ -860,254 +861,6 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return status; } -NTSTATUS libnet_set_join_secrets(struct libnet_context *ctx, - TALLOC_CTX *mem_ctx, - struct libnet_set_join_secrets *r) -{ - TALLOC_CTX *tmp_mem; - int ret, rtn; - struct ldb_context *ldb; - struct ldb_dn *base_dn; - struct ldb_message **msgs, *msg; - const char *sct; - const char * const attrs[] = { - "whenChanged", - "secret", - "priorSecret", - "priorChanged", - "krb5Keytab", - "privateKeytab", - NULL - }; - - tmp_mem = talloc_new(mem_ctx); - if (!tmp_mem) { - return NT_STATUS_NO_MEMORY; - } - - /* Open the secrets database */ - ldb = secrets_db_connect(tmp_mem, ctx->event_ctx, ctx->lp_ctx); - if (!ldb) { - r->out.error_string - = talloc_asprintf(mem_ctx, - "Could not open secrets database"); - talloc_free(tmp_mem); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* - * now prepare the record for secrets.ldb - */ - sct = talloc_asprintf(tmp_mem, "%d", r->in.join_type); - if (!sct) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - msg = ldb_msg_new(tmp_mem); - if (!msg) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - base_dn = ldb_dn_new(tmp_mem, ldb, "cn=Primary Domains"); - if (!base_dn) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - msg->dn = ldb_dn_copy(tmp_mem, base_dn); - if ( ! ldb_dn_add_child_fmt(msg->dn, "flatname=%s", r->in.domain_name)) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "flatname", r->in.domain_name); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - if (r->in.realm) { - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "realm", r->in.realm); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "primaryDomain"); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "objectClass", "kerberosSecret"); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "secret", r->in.join_password); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "samAccountName", r->in.account_name); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_add_string(ldb, tmp_mem, msg, "secureChannelType", sct); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - if (r->in.kvno) { - rtn = samdb_msg_add_uint(ldb, tmp_mem, msg, "msDS-KeyVersionNumber", - r->in.kvno); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - if (r->in.domain_sid) { - rtn = samdb_msg_add_dom_sid(ldb, tmp_mem, msg, "objectSid", - r->in.domain_sid); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - /* - * search for the secret record - * - remove the records we find - * - and fetch the old secret and store it under priorSecret - */ - ret = gendb_search(ldb, - tmp_mem, base_dn, - &msgs, attrs, - "(|" SECRETS_PRIMARY_DOMAIN_FILTER "(realm=%s))", - r->in.domain_name, r->in.realm); - if (ret == 0) { - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "privateKeytab", "secrets.keytab"); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } else if (ret == -1) { - r->out.error_string - = talloc_asprintf(mem_ctx, - "Search for domain: %s and realm: %s failed: %s", - r->in.domain_name, r->in.realm, ldb_errstring(ldb)); - talloc_free(tmp_mem); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } else { - const struct ldb_val *private_keytab; - const struct ldb_val *krb5_main_keytab; - const struct ldb_val *prior_secret; - const struct ldb_val *prior_modified_time; - int i; - - for (i = 0; i < ret; i++) { - ldb_delete(ldb, msgs[i]->dn); - } - - prior_secret = ldb_msg_find_ldb_val(msgs[0], "secret"); - if (prior_secret) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "priorSecret", prior_secret); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secret", r->in.join_password); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - prior_modified_time = ldb_msg_find_ldb_val(msgs[0], - "whenChanged"); - if (prior_modified_time) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "priorWhenChanged", - prior_modified_time); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "samAccountName", r->in.account_name); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secureChannelType", sct); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - - /* We will want to keep the keytab names */ - private_keytab = ldb_msg_find_ldb_val(msgs[0], "privateKeytab"); - if (private_keytab) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "privateKeytab", private_keytab); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - krb5_main_keytab = ldb_msg_find_ldb_val(msgs[0], "krb5Keytab"); - if (krb5_main_keytab) { - rtn = samdb_msg_set_value(ldb, tmp_mem, msg, - "krb5Keytab", krb5_main_keytab); - if (rtn == -1) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - } - } - - /* create the secret */ - ret = ldb_add(ldb, msg); - if (ret != 0) { - r->out.error_string = talloc_asprintf(mem_ctx, "Failed to create secret record %s", - ldb_dn_get_linearized(msg->dn)); - talloc_free(tmp_mem); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - return NT_STATUS_OK; -} - static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_Join *r) @@ -1115,11 +868,12 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, NTSTATUS status; TALLOC_CTX *tmp_mem; struct libnet_JoinDomain *r2; - struct libnet_set_join_secrets *r3; + struct provision_store_self_join_settings *set_secrets; uint32_t acct_type = 0; const char *account_name; const char *netbios_name; - + const char *error_string; + r->out.error_string = NULL; tmp_mem = talloc_new(mem_ctx); @@ -1179,26 +933,26 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, return status; } - r3 = talloc(tmp_mem, struct libnet_set_join_secrets); - if (!r3) { + set_secrets = talloc(tmp_mem, struct provision_store_self_join_settings); + if (!set_secrets) { r->out.error_string = NULL; talloc_free(tmp_mem); return NT_STATUS_NO_MEMORY; } - ZERO_STRUCTP(r3); - r3->in.domain_name = r2->out.domain_name; - r3->in.realm = r2->out.realm; - r3->in.account_name = account_name; - r3->in.netbios_name = netbios_name; - r3->in.join_type = r->in.join_type; - r3->in.join_password = r2->out.join_password; - r3->in.kvno = r2->out.kvno; - r3->in.domain_sid = r2->out.domain_sid; + ZERO_STRUCTP(set_secrets); + set_secrets->domain_name = r2->out.domain_name; + set_secrets->realm = r2->out.realm; + set_secrets->account_name = account_name; + set_secrets->netbios_name = netbios_name; + set_secrets->secure_channel_type = r->in.join_type; + set_secrets->machine_password = r2->out.join_password; + set_secrets->key_version_number = r2->out.kvno; + set_secrets->domain_sid = r2->out.domain_sid; - status = libnet_set_join_secrets(ctx, r3, r3); + status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string); if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_steal(mem_ctx, r3->out.error_string); + r->out.error_string = talloc_steal(mem_ctx, error_string); talloc_free(tmp_mem); return status; } @@ -1206,11 +960,11 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, /* move all out parameter to the callers TALLOC_CTX */ r->out.error_string = NULL; r->out.join_password = r2->out.join_password; - talloc_steal(mem_ctx, r2->out.join_password); + talloc_reparent(r2, mem_ctx, r2->out.join_password); r->out.domain_sid = r2->out.domain_sid; - talloc_steal(mem_ctx, r2->out.domain_sid); + talloc_reparent(r2, mem_ctx, r2->out.domain_sid); r->out.domain_name = r2->out.domain_name; - talloc_steal(mem_ctx, r2->out.domain_name); + talloc_reparent(r2, mem_ctx, r2->out.domain_name); talloc_free(tmp_mem); return NT_STATUS_OK; } diff --git a/source4/libnet/libnet_vampire.c b/source4/libnet/libnet_vampire.c index 327a64daea..19453a4d65 100644 --- a/source4/libnet/libnet_vampire.c +++ b/source4/libnet/libnet_vampire.c @@ -595,10 +595,11 @@ NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_Vampire *r) { struct libnet_JoinDomain *join; - struct libnet_set_join_secrets *set_secrets; + struct provision_store_self_join_settings *set_secrets; struct libnet_BecomeDC b; struct vampire_state *s; struct ldb_message *msg; + const char *error_string; int ldb_ret; uint32_t i; NTSTATUS status; @@ -709,40 +710,52 @@ NTSTATUS libnet_Vampire(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, return NT_STATUS_INTERNAL_DB_ERROR; } - /* commit the transaction - this commits all the changes in - the ldb from the whole vampire. Note that this commit + /* prepare the transaction - this prepares to commit all the changes in + the ldb from the whole vampire. Note that this triggers the writing of the linked attribute backlinks. */ - if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) { - printf("Failed to commit vampire transaction\n"); + if (ldb_transaction_prepare_commit(s->ldb) != LDB_SUCCESS) { + printf("Failed to prepare_commit vampire transaction\n"); return NT_STATUS_INTERNAL_DB_ERROR; } - set_secrets = talloc_zero(s, struct libnet_set_join_secrets); + set_secrets = talloc(s, struct provision_store_self_join_settings); if (!set_secrets) { + r->out.error_string = NULL; + talloc_free(s); return NT_STATUS_NO_MEMORY; } - - set_secrets->in.domain_name = join->out.domain_name; - set_secrets->in.realm = join->out.realm; - set_secrets->in.account_name = account_name; - set_secrets->in.netbios_name = netbios_name; - set_secrets->in.join_type = SEC_CHAN_BDC; - set_secrets->in.join_password = join->out.join_password; - set_secrets->in.kvno = join->out.kvno; - set_secrets->in.domain_sid = join->out.domain_sid; - status = libnet_set_join_secrets(ctx, set_secrets, set_secrets); + ZERO_STRUCTP(set_secrets); + set_secrets->domain_name = join->out.domain_name; + set_secrets->realm = join->out.realm; + set_secrets->account_name = account_name; + set_secrets->netbios_name = netbios_name; + set_secrets->secure_channel_type = SEC_CHAN_BDC; + set_secrets->machine_password = join->out.join_password; + set_secrets->key_version_number = join->out.kvno; + set_secrets->domain_sid = join->out.domain_sid; + + status = provision_store_self_join(ctx, ctx->lp_ctx, ctx->event_ctx, set_secrets, &error_string); if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_steal(mem_ctx, set_secrets->out.error_string); + r->out.error_string = talloc_steal(mem_ctx, error_string); talloc_free(s); return status; } r->out.domain_name = talloc_steal(r, join->out.domain_name); r->out.domain_sid = talloc_steal(r, join->out.domain_sid); - talloc_free(s); + /* commit the transaction now we know the secrets were written + * out properly + */ + if (ldb_transaction_commit(s->ldb) != LDB_SUCCESS) { + printf("Failed to commit vampire transaction\n"); + return NT_STATUS_INTERNAL_DB_ERROR; + } + + talloc_free(s); + return NT_STATUS_OK; } diff --git a/source4/librpc/ndr/py_security.c b/source4/librpc/ndr/py_security.c index 02dc059f05..1b185a51b5 100644 --- a/source4/librpc/ndr/py_security.c +++ b/source4/librpc/ndr/py_security.c @@ -23,6 +23,11 @@ #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None #endif +PyObject *py_dom_sid_FromSid(struct dom_sid *sid) +{ + return py_talloc_reference(&dom_sid_Type, sid); +} + static void PyType_AddMethods(PyTypeObject *type, PyMethodDef *methods) { PyObject *dict; diff --git a/source4/librpc/ndr/py_security.h b/source4/librpc/ndr/py_security.h new file mode 100644 index 0000000000..9d200faf8e --- /dev/null +++ b/source4/librpc/ndr/py_security.h @@ -0,0 +1,23 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "libcli/security/security.h" + +/* a lone prototype for this function, because it's python */ +PyObject *py_dom_sid_FromSid(struct dom_sid *sid); diff --git a/source4/param/config.mk b/source4/param/config.mk index 6e5290b64d..45eb836bb4 100644 --- a/source4/param/config.mk +++ b/source4/param/config.mk @@ -13,7 +13,7 @@ PUBLIC_HEADERS += param/param.h PC_FILES += $(paramsrcdir)/samba-hostconfig.pc [SUBSYSTEM::PROVISION] -PRIVATE_DEPENDENCIES = LIBPYTHON pyldb pyparam_util +PRIVATE_DEPENDENCIES = LIBPYTHON pyldb pyparam_util python_dcerpc_security PROVISION_OBJ_FILES = $(paramsrcdir)/provision.o $(param_OBJ_FILES) diff --git a/source4/param/provision.c b/source4/param/provision.c index bbc6837a90..355af794d8 100644 --- a/source4/param/provision.c +++ b/source4/param/provision.c @@ -2,7 +2,8 @@ Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008 - + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or @@ -20,15 +21,21 @@ #include "includes.h" #include "auth/auth.h" #include "lib/ldb_wrap.h" +#include "ldb/include/ldb.h" +#include "ldb_errors.h" #include "libcli/raw/libcliraw.h" #include "librpc/ndr/libndr.h" #include "param/param.h" #include "param/provision.h" +#include "param/secrets.h" #include <Python.h> +#include "lib/talloc/pytalloc.h" +#include "librpc/rpc/pyrpc.h" #include "scripting/python/modules.h" #include "lib/ldb/pyldb.h" #include "param/pyparam.h" +#include "librpc/ndr/py_security.h" NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct provision_settings *settings, @@ -144,3 +151,125 @@ NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, return NT_STATUS_OK; } + +extern void initldb(void); +extern void initsecurity(void); + +NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, + struct tevent_context *event_ctx, + struct provision_store_self_join_settings *settings, + const char **error_string) +{ + int ret; + PyObject *provision_mod, *provision_dict, *provision_fn, *py_result, *parameters, *py_sid; + struct ldb_context *ldb; + TALLOC_CTX *tmp_mem = talloc_new(mem_ctx); + if (!tmp_mem) { + return NT_STATUS_NO_MEMORY; + } + + /* Open the secrets database */ + ldb = secrets_db_connect(tmp_mem, event_ctx, lp_ctx); + if (!ldb) { + *error_string + = talloc_asprintf(mem_ctx, + "Could not open secrets database"); + talloc_free(tmp_mem); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + ret = ldb_transaction_start(ldb); + + if (ret != LDB_SUCCESS) { + *error_string + = talloc_asprintf(mem_ctx, + "Could not start transaction on secrets database: %s", ldb_errstring(ldb)); + talloc_free(tmp_mem); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } + + py_load_samba_modules(); + Py_Initialize(); + py_update_path("bin"); /* FIXME: Can't assume this is always the case */ + initldb(); + initsecurity(); + provision_mod = PyImport_Import(PyString_FromString("samba.provision")); + + if (provision_mod == NULL) { + PyErr_Print(); + *error_string + = talloc_asprintf(mem_ctx, "Unable to import provision Python module."); + talloc_free(tmp_mem); + return NT_STATUS_UNSUCCESSFUL; + } + + provision_dict = PyModule_GetDict(provision_mod); + + if (provision_dict == NULL) { + *error_string + = talloc_asprintf(mem_ctx, "Unable to get dictionary for provision module"); + talloc_free(tmp_mem); + return NT_STATUS_UNSUCCESSFUL; + } + + provision_fn = PyDict_GetItemString(provision_dict, "secretsdb_self_join"); + if (provision_fn == NULL) { + PyErr_Print(); + *error_string + = talloc_asprintf(mem_ctx, "Unable to get provision_become_dc function"); + talloc_free(tmp_mem); + return NT_STATUS_UNSUCCESSFUL; + } + + parameters = PyDict_New(); + + PyDict_SetItemString(parameters, "secretsdb", + PyLdb_FromLdbContext(ldb)); + PyDict_SetItemString(parameters, "domain", + PyString_FromString(settings->domain_name)); + PyDict_SetItemString(parameters, "domain", + PyString_FromString(settings->domain_name)); + PyDict_SetItemString(parameters, "realm", + PyString_FromString(settings->realm)); + PyDict_SetItemString(parameters, "machinepass", + PyString_FromString(settings->machine_password)); + PyDict_SetItemString(parameters, "netbiosname", + PyString_FromString(settings->netbios_name)); + + py_sid = py_dom_sid_FromSid(settings->domain_sid); + + PyDict_SetItemString(parameters, "domainsid", + py_sid); + + PyDict_SetItemString(parameters, "secure_channel_type", + PyInt_FromLong(settings->secure_channel_type)); + + PyDict_SetItemString(parameters, "key_version_number", + PyInt_FromLong(settings->key_version_number)); + + py_result = PyEval_CallObjectWithKeywords(provision_fn, NULL, parameters); + + Py_DECREF(parameters); + + if (py_result == NULL) { + ldb_transaction_cancel(ldb); + talloc_free(tmp_mem); + + PyErr_Print(); + PyErr_Clear(); + return NT_STATUS_UNSUCCESSFUL; + } + + ret = ldb_transaction_commit(ldb); + if (ret != LDB_SUCCESS) { + *error_string + = talloc_asprintf(mem_ctx, + "Could not commit transaction on secrets database: %s", ldb_errstring(ldb)); + talloc_free(tmp_mem); + return NT_STATUS_INTERNAL_DB_ERROR; + } + + talloc_free(tmp_mem); + + return NT_STATUS_OK; +} diff --git a/source4/param/provision.h b/source4/param/provision.h index af9685d292..c3b3bb88d8 100644 --- a/source4/param/provision.h +++ b/source4/param/provision.h @@ -44,8 +44,24 @@ struct provision_result { struct loadparm_context *lp_ctx; }; +struct provision_store_self_join_settings { + const char *domain_name; + const char *realm; + const char *netbios_name; + const char *account_name; + enum netr_SchannelType secure_channel_type; + const char *machine_password; + int key_version_number; + struct dom_sid *domain_sid; +}; + NTSTATUS provision_bare(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, struct provision_settings *settings, struct provision_result *result); +NTSTATUS provision_store_self_join(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, + struct tevent_context *ev_ctx, + struct provision_store_self_join_settings *settings, + const char **error_string); + #endif /* _PROVISION_H_ */ diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 25cec4b143..2d3e04eac1 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -44,7 +44,7 @@ from credentials import Credentials, DONT_USE_KERBEROS from auth import system_session, admin_session from samba import version, Ldb, substitute_var, valid_netbios_name from samba import check_all_substituted -from samba import DS_DOMAIN_FUNCTION_2000, DS_DC_FUNCTION_2008_R2 +from samba import DS_DOMAIN_FUNCTION_2000, DS_DOMAIN_FUNCTION_2008, DS_DC_FUNCTION_2008, DS_DC_FUNCTION_2008_R2 from samba.samdb import SamDB from samba.idmap import IDmapDB from samba.dcerpc import security @@ -54,14 +54,10 @@ from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError, timestring from ms_schema import read_ms_schema from ms_display_specifiers import read_ms_ldif from signal import SIGTERM +from dcerpc.misc import SEC_CHAN_BDC, SEC_CHAN_WKSTA __docformat__ = "restructuredText" - -class ProvisioningError(ValueError): - pass - - def find_setup_dir(): """Find the setup directory used by provision.""" dirname = os.path.dirname(__file__) @@ -113,6 +109,11 @@ def get_config_descriptor(domain_sid): DEFAULTSITE = "Default-First-Site-Name" +# Exception classes + +class ProvisioningError(Exception): + """A generic provision error.""" + class InvalidNetbiosName(Exception): """A specified name was not a valid NetBIOS name.""" def __init__(self, name): @@ -355,7 +356,6 @@ def provision_paths_from_lp(lp, dnsdomain): """ paths = ProvisionPaths() paths.private_dir = lp.get("private dir") - paths.keytab = "secrets.keytab" paths.dns_keytab = "dns.keytab" paths.shareconf = os.path.join(paths.private_dir, "share.ldb") @@ -695,26 +695,83 @@ def setup_samdb_partitions(samdb_path, setup_path, message, lp, session_info, samdb.transaction_commit() +def secretsdb_self_join(secretsdb, domain, + netbiosname, domainsid, machinepass, + realm=None, dnsdomain=None, + keytab_path=None, + key_version_number=1, + secure_channel_type=SEC_CHAN_WKSTA): + """Add domain join-specific bits to a secrets database. + + :param secretsdb: Ldb Handle to the secrets database + :param machinepass: Machine password + """ + attrs=["whenChanged", + "secret", + "priorSecret", + "priorChanged", + "krb5Keytab", + "privateKeytab"] + + + msg = ldb.Message(ldb.Dn(secretsdb, "flatname=%s,cn=Primary Domains" % domain)); + msg["secureChannelType"] = str(secure_channel_type) + msg["flatname"] = [domain] + msg["objectClass"] = ["top", "primaryDomain"] + if realm is not None: + if dnsdomain is None: + dnsdomain = realm.lower() + msg["objectClass"] = ["top", "primaryDomain", "kerberosSecret"] + msg["realm"] = realm + msg["saltPrincipal"] = "host/%s.%s@%s" % (netbiosname.lower(), dnsdomain.lower(), realm.upper()) + msg["msDS-KeyVersionNumber"] = [str(key_version_number)] + msg["privateKeytab"] = ["secrets.keytab"]; + + + msg["secret"] = [machinepass] + msg["samAccountName"] = ["%s$" % netbiosname] + msg["secureChannelType"] = [str(secure_channel_type)] + msg["objectSid"] = [ndr_pack(domainsid)] + + res = secretsdb.search(base="cn=Primary Domains", + attrs=attrs, + expression=("(&(|(flatname=%s)(realm=%s)(objectSid=%s))(objectclass=primaryDomain))" % (domain, realm, str(domainsid))), + scope=SCOPE_ONELEVEL) + + for del_msg in res: + if del_msg.dn is not msg.dn: + secretsdb.delete(del_msg.dn) + + res = secretsdb.search(base=msg.dn, attrs=attrs, scope=SCOPE_BASE) + if len(res) == 1: + msg["priorSecret"] = res[0]["secret"] + msg["priorWhenChanged"] = res[0]["whenChanged"] -def secretsdb_become_dc(secretsdb, setup_path, domain, realm, dnsdomain, - netbiosname, domainsid, keytab_path, samdb_url, - dns_keytab_path, dnspass, machinepass): - """Add DC-specific bits to a secrets database. + if res["privateKeytab"] is not None: + msg["privateKeytab"] = res[0]["privateKeytab"] + + if res["krb5Keytab"] is not None: + msg["krb5Keytab"] = res[0]["krb5Keytab"] + + for el in msg: + el.set_flags(ldb.FLAG_MOD_REPLACE) + secretsdb.modify(msg) + else: + secretsdb.add(msg) + + +def secretsdb_setup_dns(secretsdb, setup_path, realm, dnsdomain, + dns_keytab_path, dnspass): + """Add DNS specific bits to a secrets database. :param secretsdb: Ldb Handle to the secrets database :param setup_path: Setup path function :param machinepass: Machine password """ - setup_ldb(secretsdb, setup_path("secrets_dc.ldif"), { - "MACHINEPASS_B64": b64encode(machinepass), - "DOMAIN": domain, + setup_ldb(secretsdb, setup_path("secrets_dns.ldif"), { "REALM": realm, "DNSDOMAIN": dnsdomain, - "DOMAINSID": str(domainsid), - "SECRETS_KEYTAB": keytab_path, - "NETBIOSNAME": netbiosname, - "SAM_LDB": samdb_url, "DNS_KEYTAB": dns_keytab_path, "DNSPASS_B64": b64encode(dnspass), }) @@ -738,6 +795,7 @@ def setup_secretsdb(path, setup_path, session_info, credentials, lp): secrets_ldb.load_ldif_file_add(setup_path("secrets_init.ldif")) secrets_ldb = Ldb(path, session_info=session_info, credentials=credentials, lp=lp) + secrets_ldb.transaction_start() secrets_ldb.load_ldif_file_add(setup_path("secrets.ldif")) if credentials is not None and credentials.authentication_requested(): @@ -873,9 +931,10 @@ def setup_samdb(path, setup_path, session_info, credentials, lp, :note: This will wipe the main SAM database file! """ - domainFunctionality = DS_DOMAIN_FUNCTION_2000 - forestFunctionality = DS_DOMAIN_FUNCTION_2000 - domainControllerFunctionality = DS_DC_FUNCTION_2008_R2 + # Do NOT change these default values without discussion with the team and reslease manager. + domainFunctionality = DS_DOMAIN_FUNCTION_2008 + forestFunctionality = DS_DOMAIN_FUNCTION_2008 + domainControllerFunctionality = DS_DC_FUNCTION_2008 # Also wipes the database setup_samdb_partitions(path, setup_path, message=message, lp=lp, @@ -1275,16 +1334,18 @@ def provision(setup_dir, message, session_info, # Only make a zone file on the first DC, it should be replicated with DNS replication if serverrole == "domain controller": - secrets_ldb = Ldb(paths.secrets, session_info=session_info, - credentials=credentials, lp=lp) - secretsdb_become_dc(secrets_ldb, setup_path, domain=domain, + secretsdb_self_join(secrets_ldb, domain=domain, realm=names.realm, + dnsdomain=names.dnsdomain, netbiosname=names.netbiosname, domainsid=domainsid, - keytab_path=paths.keytab, samdb_url=paths.samdb, + machinepass=machinepass, + secure_channel_type=SEC_CHAN_BDC) + + secretsdb_setup_dns(secrets_ldb, setup_path, + realm=names.realm, dnsdomain=names.dnsdomain, dns_keytab_path=paths.dns_keytab, - dnspass=dnspass, machinepass=machinepass, - dnsdomain=names.dnsdomain) + dnspass=dnspass) domainguid = samdb.searchone(basedn=domaindn, attribute="objectGUID") assert isinstance(domainguid, str) @@ -1309,6 +1370,8 @@ def provision(setup_dir, message, session_info, realm=names.realm) message("A Kerberos configuration suitable for Samba 4 has been generated at %s" % paths.krb5conf) + #Now commit the secrets.ldb to disk + secrets_ldb.transaction_commit() if provision_backend is not None: if ldap_backend_type == "fedora-ds": diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py index 239dd6a6ea..39cf1d6c40 100644 --- a/source4/scripting/python/samba/samdb.py +++ b/source4/scripting/python/samba/samdb.py @@ -202,8 +202,8 @@ userPassword:: %s self.transaction_start() try: res = self.search(base=self.domain_dn(), scope=ldb.SCOPE_SUBTREE, - expression=filter, - attrs=["userAccountControl", "accountExpires"]) + expression=filter, + attrs=["userAccountControl", "accountExpires"]) assert(len(res) == 1) user_dn = res[0].dn diff --git a/source4/setup/domainlevel b/source4/setup/domainlevel index b49150ff2d..ceab735c8f 100755 --- a/source4/setup/domainlevel +++ b/source4/setup/domainlevel @@ -39,6 +39,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--quiet", help="Be quiet", action="store_true") parser.add_option("--forest", help="The forest function level (2000 | 2003 | 2008 | 2008_R2). We don't support the 2003 with mixed domains (NT4 DC support) level.", type=str) @@ -60,8 +61,12 @@ if len(args) == 0: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) domain_dn = SamDB.domain_dn(samdb) diff --git a/source4/setup/enableaccount b/source4/setup/enableaccount index 0ca5b39faa..f8f727c1ee 100755 --- a/source4/setup/enableaccount +++ b/source4/setup/enableaccount @@ -36,6 +36,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--filter", help="LDAP Filter to set password on", type=str) opts, args = parser.parse_args() @@ -54,6 +55,11 @@ if filter is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.enable_account(filter) diff --git a/source4/setup/newuser b/source4/setup/newuser index 10af55a458..ef65d36dfb 100755 --- a/source4/setup/newuser +++ b/source4/setup/newuser @@ -37,6 +37,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--unixname", help="Unix Username", type=str) parser.add_option("--must-change-at-next-login", help="Force password to be changed on next login", action="store_true") @@ -58,6 +59,11 @@ if opts.unixname is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.newuser(username, opts.unixname, password, force_password_change_at_next_login_req=opts.must_change_at_next_login) diff --git a/source4/setup/pwsettings b/source4/setup/pwsettings index 6a5e18ef59..0bb39d9757 100755 --- a/source4/setup/pwsettings +++ b/source4/setup/pwsettings @@ -39,6 +39,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--quiet", help="Be quiet", action="store_true") parser.add_option("--complexity", help="The password complexity (on | off | default). Default is 'on'", type=str) @@ -67,8 +68,12 @@ if len(args) == 0: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) domain_dn = SamDB.domain_dn(samdb) res = samdb.search(domain_dn, scope=ldb.SCOPE_BASE, diff --git a/source4/setup/secrets_dc.ldif b/source4/setup/secrets_dc.ldif deleted file mode 100644 index b8251eece5..0000000000 --- a/source4/setup/secrets_dc.ldif +++ /dev/null @@ -1,24 +0,0 @@ -dn: flatname=${DOMAIN},CN=Primary Domains -objectClass: top -objectClass: primaryDomain -objectClass: kerberosSecret -flatname: ${DOMAIN} -realm: ${REALM} -secret:: ${MACHINEPASS_B64} -secureChannelType: 6 -sAMAccountName: ${NETBIOSNAME}$ -msDS-KeyVersionNumber: 1 -objectSid: ${DOMAINSID} -privateKeytab: ${SECRETS_KEYTAB} - -#Update a keytab for the external DNS server to use -dn: servicePrincipalName=DNS/${DNSDOMAIN},CN=Principals -objectClass: top -objectClass: secret -objectClass: kerberosSecret -realm: ${REALM} -servicePrincipalName: DNS/${DNSDOMAIN} -msDS-KeyVersionNumber: 1 -privateKeytab: ${DNS_KEYTAB} -secret:: ${DNSPASS_B64} - diff --git a/source4/setup/secrets_dns.ldif b/source4/setup/secrets_dns.ldif new file mode 100644 index 0000000000..8a19733d19 --- /dev/null +++ b/source4/setup/secrets_dns.ldif @@ -0,0 +1,11 @@ +#Update a keytab for the external DNS server to use +dn: servicePrincipalName=DNS/${DNSDOMAIN},CN=Principals +objectClass: top +objectClass: secret +objectClass: kerberosSecret +realm: ${REALM} +servicePrincipalName: DNS/${DNSDOMAIN} +msDS-KeyVersionNumber: 1 +privateKeytab: ${DNS_KEYTAB} +secret:: ${DNSPASS_B64} + diff --git a/source4/setup/secrets_self_join.ldif b/source4/setup/secrets_self_join.ldif new file mode 100644 index 0000000000..22be0cab0b --- /dev/null +++ b/source4/setup/secrets_self_join.ldif @@ -0,0 +1,13 @@ +dn: flatname=${DOMAIN},CN=Primary Domains +objectClass: top +objectClass: primaryDomain +objectClass: kerberosSecret +flatname: ${DOMAIN} +realm: ${REALM} +secret:: ${MACHINEPASS_B64} +secureChannelType: 6 +sAMAccountName: ${NETBIOSNAME}$ +msDS-KeyVersionNumber: ${KEY_VERSION_NUMBER} +objectSid: ${DOMAINSID} +privateKeytab: ${SECRETS_KEYTAB} +saltPrincipal: ${SALT_PRINCIPAL} diff --git a/source4/setup/setexpiry b/source4/setup/setexpiry index 1572555b8c..2740326f2b 100755 --- a/source4/setup/setexpiry +++ b/source4/setup/setexpiry @@ -37,12 +37,15 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--filter", help="LDAP Filter to set password on", type=str) parser.add_option("--days", help="Days to expiry", type=int) parser.add_option("--noexpiry", help="Password does never expire", action="store_true") opts, args = parser.parse_args() +filter = opts.filter + if (len(args) == 0) and (filter is None): print "Either the username or '--filter' must be specified!" parser.print_usage() @@ -59,6 +62,11 @@ if filter is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + samdb.setexpiry(filter, days*24*3600, no_expiry_req=opts.noexpiry) diff --git a/source4/setup/setpassword b/source4/setup/setpassword index d8a2a1144a..57772be7a7 100755 --- a/source4/setup/setpassword +++ b/source4/setup/setpassword @@ -38,6 +38,7 @@ parser.add_option_group(sambaopts) parser.add_option_group(options.VersionOptions(parser)) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) +parser.add_option("-H", help="LDB URL for database or target server", type=str) parser.add_option("--filter", help="LDAP Filter to set password on", type=str) parser.add_option("--newpassword", help="Set password", type=str) parser.add_option("--must-change-at-next-login", help="Force password to be changed on next login", action="store_true") @@ -62,7 +63,12 @@ if filter is None: lp = sambaopts.get_loadparm() creds = credopts.get_credentials(lp) -samdb = SamDB(url=lp.get("sam database"), session_info=system_session(), - credentials=creds, lp=lp) -samdb.setpassword(filter, password, force_password_change_at_next_login=opts.must_change_at_next_login) +if opts.H is not None: + url = opts.H +else: + url = lp.get("sam database") + +samdb = SamDB(url=url, session_info=system_session(), credentials=creds, lp=lp) + +samdb.setpassword(filter, password, force_password_change_at_next_login_req=opts.must_change_at_next_login) diff --git a/testprogs/blackbox/test_kinit.sh b/testprogs/blackbox/test_kinit.sh index 0a15802a28..91f21f473b 100755 --- a/testprogs/blackbox/test_kinit.sh +++ b/testprogs/blackbox/test_kinit.sh @@ -69,7 +69,7 @@ echo $USERPASS > ./tmpuserpassfile testit "set user password with kerberos ccache" $VALGRIND $net password set $DOMAIN\\nettestuser $USERPASS $CONFIGURATION -k yes $@ || failed=`expr $failed + 1` -testit "enable user with kerberos cache" $VALGRIND $enableaccount nettestuser -k yes $@ || failed=`expr $failed + 1` +testit "enable user with kerberos cache" $VALGRIND $enableaccount nettestuser -H ldap://$SERVER -k yes $@ || failed=`expr $failed + 1` KRB5CCNAME="$PREFIX/tmpuserccache" export KRB5CCNAME |