X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source4%2Flibnet%2Flibnet_join.c;h=9404bc874d9077921a17152bd13e1fd3d1123de4;hb=ffeee68e4b72dd94fee57366bd8d38b8c284c3d4;hp=c55be7e73ccf35e179816a840055ca55b7836ced;hpb=8e0948bbad959f8809a19e40e6777705013f866c;p=kai%2Fsamba.git diff --git a/source4/libnet/libnet_join.c b/source4/libnet/libnet_join.c index c55be7e73cc..9404bc874d9 100644 --- a/source4/libnet/libnet_join.c +++ b/source4/libnet/libnet_join.c @@ -7,7 +7,7 @@ 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 2 of the License, or + 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, @@ -16,184 +16,22 @@ 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, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" #include "libnet/libnet.h" -#include "librpc/gen_ndr/ndr_samr.h" -#include "librpc/gen_ndr/ndr_lsa.h" -#include "librpc/gen_ndr/ndr_drsuapi.h" +#include "librpc/gen_ndr/ndr_drsuapi_c.h" #include "lib/ldb/include/ldb.h" #include "lib/ldb/include/ldb_errors.h" -#include "libcli/cldap/cldap.h" -#include "include/secrets.h" -#include "librpc/gen_ndr/drsuapi.h" - -/* - * find out Site specific stuff: - * 1.) setup an CLDAP socket - * 2.) lookup the Site name - * 3.) Add entry CN=,CN=Servers,CN=,CN=Sites,CN=Configuration,. - * TODO: 4.) use DsAddEntry() to create CN=NTDS Settings,CN=,CN=Servers,CN=... - */ -static NTSTATUS libnet_JoinSite(struct libnet_context *ctx, - struct dcerpc_pipe *drsuapi_pipe, - struct policy_handle drsuapi_bind_handle, - struct ldb_context *remote_ldb, - struct libnet_JoinDomain *libnet_r) -{ - NTSTATUS status; - TALLOC_CTX *tmp_ctx; - - struct cldap_socket *cldap = NULL; - struct cldap_netlogon search; - - struct ldb_dn *server_dn; - struct ldb_message *msg; - int rtn; - - const char *site_name; - const char *server_dn_str; - const char *config_dn_str; - - tmp_ctx = talloc_named(libnet_r, 0, "libnet_JoinSite temp context"); - if (!tmp_ctx) { - libnet_r->out.error_string = NULL; - return NT_STATUS_NO_MEMORY; - } - - /* Resolve the site name. */ - - ZERO_STRUCT(search); - search.in.dest_address = libnet_r->out.samr_binding->host; - search.in.acct_control = -1; - search.in.version = 6; - - cldap = cldap_socket_init(tmp_ctx, NULL); - status = cldap_netlogon(cldap, tmp_ctx, &search); - if (!NT_STATUS_IS_OK(status)) { - /* Default to using Default-First-Site-Name rather than returning status at this point. */ - site_name = talloc_asprintf(tmp_ctx, "%s", "Default-First-Site-Name"); - if (!site_name) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - } else { - site_name = search.out.netlogon.logon5.site_name; - } - - config_dn_str = talloc_asprintf(tmp_ctx, "CN=Configuration,%s", libnet_r->out.domain_dn_str); - if (!config_dn_str) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - server_dn_str = talloc_asprintf(tmp_ctx, "CN=%s,CN=Servers,CN=%s,CN=Sites,%s", - libnet_r->in.netbios_name, site_name, config_dn_str); - if (!server_dn_str) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - /* - Add entry CN=,CN=Servers,CN=,CN=Sites,CN=Configuration,. - */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - rtn = ldb_msg_add_string(msg, "objectClass", "server"); - if (rtn != 0) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - rtn = ldb_msg_add_string(msg, "systemFlags", "50000000"); - if (rtn != 0) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - rtn = ldb_msg_add_string(msg, "serverReference",libnet_r->out.account_dn_str); - if (rtn != 0) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - server_dn = ldb_dn_explode(tmp_ctx, server_dn_str); - if (server_dn == NULL) { - libnet_r->out.error_string = talloc_asprintf(libnet_r, - "Invalid server dn: %s", - server_dn_str); - talloc_free(tmp_ctx); - return NT_STATUS_UNSUCCESSFUL; - } - - msg->dn = server_dn; - - rtn = ldb_add(remote_ldb, msg); - if (rtn == LDB_ERR_ENTRY_ALREADY_EXISTS) { - int i; - - /* make a 'modify' msg, and only for serverReference */ - msg = ldb_msg_new(tmp_ctx); - if (!msg) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - msg->dn = server_dn; - - rtn = ldb_msg_add_string(msg, "serverReference",libnet_r->out.account_dn_str); - if (rtn != 0) { - libnet_r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - /* mark all the message elements (should be just one) - as LDB_FLAG_MOD_REPLACE */ - for (i=0;inum_elements;i++) { - msg->elements[i].flags = LDB_FLAG_MOD_REPLACE; - } - - rtn = ldb_modify(remote_ldb, msg); - if (rtn != 0) { - libnet_r->out.error_string - = talloc_asprintf(libnet_r, - "Failed to modify server entry %s: %s: %d", - server_dn_str, - ldb_errstring(remote_ldb), rtn); - talloc_free(tmp_ctx); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - } else if (rtn != 0) { - libnet_r->out.error_string - = talloc_asprintf(libnet_r, - "Failed to add server entry %s: %s: %d", - server_dn_str, - ldb_errstring(remote_ldb), rtn); - talloc_free(tmp_ctx); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - DEBUG(0, ("We still need to perform a DsAddEntry() so that we can create the CN=NTDS Settings container.\n")); - - /* Store the server DN in libnet_r */ - libnet_r->out.server_dn_str = server_dn_str; - talloc_steal(libnet_r, server_dn_str); - - talloc_free(tmp_ctx); - return NT_STATUS_OK; -} +#include "param/secrets.h" +#include "dsdb/samdb/samdb.h" +#include "db_wrap.h" +#include "libcli/security/security.h" +#include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_krb5.h" +#include "librpc/gen_ndr/ndr_samr_c.h" +#include "param/param.h" /* * complete a domain join, when joining to a AD domain: @@ -224,7 +62,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J struct GUID drsuapi_bind_guid; struct ldb_context *remote_ldb; - const struct ldb_dn *account_dn; + struct ldb_dn *account_dn; const char *account_dn_str; const char *remote_ldb_url; struct ldb_result *res; @@ -232,12 +70,11 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J int ret, rtn; - unsigned int kvno; - const char * const attrs[] = { "msDS-KeyVersionNumber", "servicePrincipalName", "dNSHostName", + "objectGUID", NULL, }; @@ -274,14 +111,13 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J status = dcerpc_pipe_connect_b(tmp_ctx, &drsuapi_pipe, drsuapi_binding, - DCERPC_DRSUAPI_UUID, - DCERPC_DRSUAPI_VERSION, + &ndr_table_drsuapi, ctx->cred, ctx->event_ctx); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(r, "Connection to DRSUAPI pipe of PDC of domain '%s' failed: %s", - r->in.domain_name, + r->out.domain_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; @@ -299,16 +135,14 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { r->out.error_string = talloc_asprintf(r, - "dcerpc_drsuapi_DsBind for [%s\\%s] failed - %s\n", - r->in.domain_name, r->in.account_name, + "dcerpc_drsuapi_DsBind failed - %s", dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code)); talloc_free(tmp_ctx); return status; } else { r->out.error_string = talloc_asprintf(r, - "dcerpc_drsuapi_DsBind for [%s\\%s] failed - %s\n", - r->in.domain_name, r->in.account_name, + "dcerpc_drsuapi_DsBind failed - %s", nt_errstr(status)); talloc_free(tmp_ctx); return status; @@ -316,7 +150,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J } else if (!W_ERROR_IS_OK(r_drsuapi_bind.out.result)) { r->out.error_string = talloc_asprintf(r, - "DsBind failed - %s\n", + "DsBind failed - %s", win_errstr(r_drsuapi_bind.out.result)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; @@ -326,8 +160,8 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J ZERO_STRUCT(r_crack_names); r_crack_names.in.bind_handle = &drsuapi_bind_handle; r_crack_names.in.level = 1; - r_crack_names.in.req.req1.unknown1 = 0x000004e4; - r_crack_names.in.req.req1.unknown2 = 0x00000407; + r_crack_names.in.req.req1.codepage = 1252; /* western european */ + r_crack_names.in.req.req1.language = 0x00000407; /* german */ r_crack_names.in.req.req1.count = 1; r_crack_names.in.req.req1.names = names; r_crack_names.in.req.req1.format_flags = DRSUAPI_DS_NAME_FLAG_NO_FLAGS; @@ -345,7 +179,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { r->out.error_string = talloc_asprintf(r, - "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s\n", + "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", names[0].str, dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code)); talloc_free(tmp_ctx); @@ -353,7 +187,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J } else { r->out.error_string = talloc_asprintf(r, - "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s\n", + "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", names[0].str, nt_errstr(status)); talloc_free(tmp_ctx); @@ -362,34 +196,32 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J } else if (!W_ERROR_IS_OK(r_crack_names.out.result)) { r->out.error_string = talloc_asprintf(r, - "DsCrackNames failed - %s\n", win_errstr(r_crack_names.out.result)); + "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } else if (r_crack_names.out.level != 1 || !r_crack_names.out.ctr.ctr1 - || r_crack_names.out.ctr.ctr1->count != 1 - || !r_crack_names.out.ctr.ctr1->array[0].result_name - || r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { - r->out.error_string = talloc_asprintf(r, "DsCrackNames failed\n"); + || r_crack_names.out.ctr.ctr1->count != 1) { + r->out.error_string = talloc_asprintf(r, "DsCrackNames failed"); + talloc_free(tmp_ctx); + return NT_STATUS_INVALID_PARAMETER; + } else if (r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { + r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: %d", r_crack_names.out.ctr.ctr1->array[0].status); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; + } else if (r_crack_names.out.ctr.ctr1->array[0].result_name == NULL) { + r->out.error_string = talloc_asprintf(r, "DsCrackNames failed: no result name"); + talloc_free(tmp_ctx); + return NT_STATUS_INVALID_PARAMETER; } /* Store the DN of our machine account. */ account_dn_str = r_crack_names.out.ctr.ctr1->array[0].result_name; - account_dn = ldb_dn_explode(tmp_ctx, account_dn_str); - if (!account_dn) { - r->out.error_string = talloc_asprintf(r, "Invalid account dn: %s", - account_dn_str); - talloc_free(tmp_ctx); - return NT_STATUS_UNSUCCESSFUL; - } - /* Now we know the user's DN, open with LDAP, read and modify a few things */ remote_ldb_url = talloc_asprintf(tmp_ctx, "ldap://%s", - drsuapi_binding->host); + drsuapi_binding->target_hostname); if (!remote_ldb_url) { r->out.error_string = NULL; talloc_free(tmp_ctx); @@ -404,18 +236,32 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J return NT_STATUS_UNSUCCESSFUL; } + account_dn = ldb_dn_new(tmp_ctx, remote_ldb, account_dn_str); + if (! ldb_dn_validate(account_dn)) { + r->out.error_string = talloc_asprintf(r, "Invalid account dn: %s", + account_dn_str); + talloc_free(tmp_ctx); + return NT_STATUS_UNSUCCESSFUL; + } + /* search for the user's record */ ret = ldb_search(remote_ldb, account_dn, LDB_SCOPE_BASE, - NULL, attrs, &res); - if (ret != LDB_SUCCESS || res->count != 1) { - r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s\n", + NULL, attrs, &res); + if (ret != LDB_SUCCESS) { + r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - %s", account_dn_str, ldb_errstring(remote_ldb)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } - /* If we have a kvno recorded in AD, we need it locally as well */ - kvno = ldb_msg_find_uint(res->msgs[0], "msDS-KeyVersionNumber", 0); + talloc_steal(tmp_ctx, res); + + if (res->count != 1) { + r->out.error_string = talloc_asprintf(r, "ldb_search for %s failed - found %d entries", + account_dn_str, res->count); + talloc_free(tmp_ctx); + return NT_STATUS_UNSUCCESSFUL; + } /* Prepare a new message, for the modify */ msg = ldb_msg_new(tmp_ctx); @@ -473,8 +319,8 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J if (rtn != 0) { r->out.error_string = talloc_asprintf(r, - "Failed to replace entries on %s\n", - ldb_dn_linearize(tmp_ctx, msg->dn)); + "Failed to replace entries on %s", + ldb_dn_get_linearized(msg->dn)); talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -495,7 +341,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J if (NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { r->out.error_string = talloc_asprintf(r, - "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s\n", + "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", r->in.domain_name, dcerpc_errstr(tmp_ctx, drsuapi_pipe->last_fault_code)); talloc_free(tmp_ctx); @@ -503,7 +349,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J } else { r->out.error_string = talloc_asprintf(r, - "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s\n", + "dcerpc_drsuapi_DsCrackNames for [%s] failed - %s", r->in.domain_name, nt_errstr(status)); talloc_free(tmp_ctx); @@ -512,7 +358,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J } else if (!W_ERROR_IS_OK(r_crack_names.out.result)) { r->out.error_string = talloc_asprintf(r, - "DsCrackNames failed - %s\n", win_errstr(r_crack_names.out.result)); + "DsCrackNames failed - %s", win_errstr(r_crack_names.out.result)); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } else if (r_crack_names.out.level != 1 @@ -520,7 +366,7 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J || r_crack_names.out.ctr.ctr1->count != 1 || !r_crack_names.out.ctr.ctr1->array[0].result_name || r_crack_names.out.ctr.ctr1->array[0].status != DRSUAPI_DS_NAME_STATUS_OK) { - r->out.error_string = talloc_asprintf(r, "DsCrackNames failed\n"); + r->out.error_string = talloc_asprintf(r, "DsCrackNames failed"); talloc_free(tmp_ctx); return NT_STATUS_UNSUCCESSFUL; } @@ -533,12 +379,15 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J r->out.domain_dn_str = r_crack_names.out.ctr.ctr1->array[0].result_name; talloc_steal(r, r_crack_names.out.ctr.ctr1->array[0].result_name); - r->out.kvno = kvno; + /* Store the KVNO of the account, critical for some kerberos + * operations */ + r->out.kvno = ldb_msg_find_attr_as_uint(res->msgs[0], "msDS-KeyVersionNumber", 0); - if (r->in.acct_type == ACB_SVRTRUST) { - status = libnet_JoinSite(ctx, - drsuapi_pipe, drsuapi_bind_handle, - remote_ldb, r); + /* Store the account GUID. */ + r->out.account_guid = samdb_result_guid(res->msgs[0], "objectGUID"); + + if (r->in.acct_type == ACB_SVRTRUST) { + status = libnet_JoinSite(remote_ldb, r); } talloc_free(tmp_ctx); @@ -547,21 +396,23 @@ static NTSTATUS libnet_JoinADSDomain(struct libnet_context *ctx, struct libnet_J /* * do a domain join using DCERPC/SAMR calls - * 1. connect to the SAMR pipe of users domain PDC (maybe a standalone server or workstation) - * is it correct to contact the the pdc of the domain of the user who's password should be set? - * 2. do a samr_Connect to get a policy handle - * 3. do a samr_LookupDomain to get the domain sid - * 4. do a samr_OpenDomain to get a domain handle - * 5. do a samr_CreateAccount to try and get a new account + * - connect to the LSA pipe, to try and find out information about the domain + * - create a secondary connection to SAMR pipe + * - do a samr_Connect to get a policy handle + * - do a samr_LookupDomain to get the domain sid + * - do a samr_OpenDomain to get a domain handle + * - do a samr_CreateAccount to try and get a new account * * If that fails, do: - * 5.1. do a samr_LookupNames to get the users rid - * 5.2. do a samr_OpenUser to get a user handle + * - do a samr_LookupNames to get the users rid + * - do a samr_OpenUser to get a user handle + * - potentially delete and recreate the user + * - assert the account is of the right type with samrQueryUserInfo * - * 6. call libnet_SetPassword_samr_handle to set the password + * - call libnet_SetPassword_samr_handle to set the password, + * and pass a samr_UserInfo21 struct to set full_name and the account flags * - * 7. do a samrSetUserInfo to set the account flags - * 8. do some ADS specific things when we join as Domain Controller, + * - do some ADS specific things when we join as Domain Controller, * look at libnet_joinADSDomain() for the details */ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_JoinDomain *r) @@ -569,17 +420,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru TALLOC_CTX *tmp_ctx; NTSTATUS status, cu_status; - struct libnet_RpcConnect *c; - struct lsa_ObjectAttribute attr; - struct lsa_QosInfo qos; - struct lsa_OpenPolicy2 lsa_open_policy; - struct policy_handle lsa_p_handle; - struct lsa_QueryInfoPolicy2 lsa_query_info2; - struct lsa_QueryInfoPolicy lsa_query_info; - - struct dcerpc_binding *samr_binding; + + struct libnet_RpcConnect *connect_with_info; struct dcerpc_pipe *samr_pipe; - struct dcerpc_pipe *lsa_pipe; + struct samr_Connect sc; struct policy_handle p_handle; struct samr_OpenDomain od; @@ -589,8 +433,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru struct samr_CreateUser2 cu; struct policy_handle *u_handle = NULL; struct samr_QueryUserInfo qui; - struct samr_SetUserInfo sui; - union samr_UserInfo u_info; + struct samr_UserInfo21 u_info21; union libnet_SetPassword r2; struct samr_GetUserPwInfo pwp; struct lsa_String samr_account_name; @@ -599,12 +442,8 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru uint32_t rid, access_granted; int policy_min_pw_len = 0; - struct dom_sid *domain_sid = NULL; struct dom_sid *account_sid = NULL; - const char *domain_name = NULL; const char *password_str = NULL; - const char *realm = NULL; /* Also flag for remote being AD */ - r->out.error_string = NULL; r2.samr_handle.out.error_string = NULL; @@ -622,170 +461,50 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return NT_STATUS_NO_MEMORY; } - samr_pipe = talloc(tmp_ctx, struct dcerpc_pipe); - if (!samr_pipe) { + connect_with_info = talloc(tmp_ctx, struct libnet_RpcConnect); + if (!connect_with_info) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } - - c = talloc(tmp_ctx, struct libnet_RpcConnect); - if (!c) { - r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - /* prepare connect to the LSA pipe of PDC */ + + /* prepare connect to the SAMR pipe of PDC */ if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { - c->level = LIBNET_RPC_CONNECT_PDC; - c->in.domain_name = r->in.domain_name; + connect_with_info->in.binding = NULL; + connect_with_info->in.name = r->in.domain_name; } else { - c->level = LIBNET_RPC_CONNECT_BINDING; - c->in.binding = r->in.binding; + connect_with_info->in.binding = r->in.binding; + connect_with_info->in.name = NULL; } - c->in.dcerpc_iface_name = DCERPC_LSARPC_NAME; - c->in.dcerpc_iface_uuid = DCERPC_LSARPC_UUID; - c->in.dcerpc_iface_version = DCERPC_LSARPC_VERSION; - - /* connect to the LSA pipe of the PDC */ - status = libnet_RpcConnect(ctx, c, c); + /* This level makes a connection to the LSA pipe on the way, + * to get some useful bits of information about the domain */ + connect_with_info->level = LIBNET_RPC_CONNECT_DC_INFO; + connect_with_info->in.dcerpc_iface = &ndr_table_samr; + + /* + establish the SAMR connection + */ + status = libnet_RpcConnect(ctx, tmp_ctx, connect_with_info); if (!NT_STATUS_IS_OK(status)) { - if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { + if (r->in.binding) { r->out.error_string = talloc_asprintf(mem_ctx, - "Connection to LSA pipe of PDC of domain '%s' failed: %s", - r->in.domain_name, nt_errstr(status)); + "Connection to SAMR pipe of DC %s failed: %s", + r->in.binding, connect_with_info->out.error_string); } else { r->out.error_string = talloc_asprintf(mem_ctx, - "Connection to LSA pipe with binding '%s' failed: %s", - r->in.binding, nt_errstr(status)); - } - talloc_free(tmp_ctx); - return status; - } - lsa_pipe = c->out.dcerpc_pipe; - - /* Get an LSA policy handle */ - - ZERO_STRUCT(lsa_p_handle); - qos.len = 0; - qos.impersonation_level = 2; - qos.context_mode = 1; - qos.effective_only = 0; - - attr.len = 0; - attr.root_dir = NULL; - attr.object_name = NULL; - attr.attributes = 0; - attr.sec_desc = NULL; - attr.sec_qos = &qos; - - lsa_open_policy.in.attr = &attr; - - lsa_open_policy.in.system_name = talloc_asprintf(tmp_ctx, "\\"); - if (!lsa_open_policy.in.system_name) { - r->out.error_string = NULL; - talloc_free(tmp_ctx); - return NT_STATUS_NO_MEMORY; - } - - lsa_open_policy.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - lsa_open_policy.out.handle = &lsa_p_handle; - - status = dcerpc_lsa_OpenPolicy2(lsa_pipe, tmp_ctx, &lsa_open_policy); - - /* This now fails on ncacn_ip_tcp against Win2k3 SP1 */ - if (NT_STATUS_IS_OK(status)) { - /* Look to see if this is ADS (a fault indicates NT4 or Samba 3.0) */ - - lsa_query_info2.in.handle = &lsa_p_handle; - lsa_query_info2.in.level = LSA_POLICY_INFO_DNS; - - status = dcerpc_lsa_QueryInfoPolicy2(lsa_pipe, tmp_ctx, - &lsa_query_info2); - - if (!NT_STATUS_EQUAL(status, NT_STATUS_NET_WRITE_FAULT)) { - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "lsa_QueryInfoPolicy2 failed: %s", - nt_errstr(status)); - talloc_free(tmp_ctx); - return status; - } - realm = lsa_query_info2.out.info->dns.dns_domain.string; - } - - /* Grab the domain SID (regardless of the result of the previous call */ - - lsa_query_info.in.handle = &lsa_p_handle; - lsa_query_info.in.level = LSA_POLICY_INFO_DOMAIN; - - status = dcerpc_lsa_QueryInfoPolicy(lsa_pipe, tmp_ctx, - &lsa_query_info); - - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "lsa_QueryInfoPolicy2 failed: %s", - nt_errstr(status)); - talloc_free(tmp_ctx); - return status; - } - - domain_sid = lsa_query_info.out.info->domain.sid; - domain_name = lsa_query_info.out.info->domain.name.string; - } else { - /* Cause the code further down to try this with just SAMR */ - domain_sid = NULL; - if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { - domain_name = talloc_strdup(tmp_ctx, r->in.domain_name); - } else { - /* Bugger, we just lost our way to automaticly find the domain name */ - domain_name = talloc_strdup(tmp_ctx, lp_workgroup()); + "Connection to SAMR pipe of PDC for %s failed: %s", + r->in.domain_name, connect_with_info->out.error_string); } - } - - DEBUG(0, ("Joining domain %s\n", domain_name)); - - /* - establish a SAMR connection, on the same CIFS transport - */ - - /* Find the original binding string */ - status = dcerpc_parse_binding(tmp_ctx, lsa_pipe->conn->binding_string, &samr_binding); - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "Failed to parse lsa binding '%s'", - lsa_pipe->conn->binding_string); talloc_free(tmp_ctx); return status; } - /* Make binding string for samr, not the other pipe */ - status = dcerpc_epm_map_binding(tmp_ctx, samr_binding, - DCERPC_SAMR_UUID, DCERPC_SAMR_VERSION, - lsa_pipe->conn->event_ctx); - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s", - DCERPC_NETLOGON_UUID, - nt_errstr(status)); - talloc_free(tmp_ctx); - return status; - } + samr_pipe = connect_with_info->out.dcerpc_pipe; - /* Setup a SAMR connection */ - status = dcerpc_secondary_connection(lsa_pipe, &samr_pipe, samr_binding); - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "SAMR secondary connection failed: %s", - nt_errstr(status)); - talloc_free(tmp_ctx); - return status; - } - - status = dcerpc_pipe_auth(samr_pipe, samr_binding, DCERPC_SAMR_UUID, - DCERPC_SAMR_VERSION, ctx->cred); + status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe, + connect_with_info->out.dcerpc_pipe->binding, + &ndr_table_samr, ctx->cred); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, "SAMR bind failed: %s", @@ -810,11 +529,22 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return status; } + /* If this is a connection on ncacn_ip_tcp to Win2k3 SP1, we don't get back this useful info */ + if (!connect_with_info->out.domain_name) { + if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) { + connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name); + } else { + /* Bugger, we just lost our way to automaticly find the domain name */ + connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lp_workgroup()); + connect_with_info->out.realm = talloc_strdup(tmp_ctx, lp_realm()); + } + } + /* Perhaps we didn't get a SID above, because we are against ncacn_ip_tcp */ - if (!domain_sid) { + if (!connect_with_info->out.domain_sid) { struct lsa_String name; struct samr_LookupDomain l; - name.string = domain_name; + name.string = connect_with_info->out.domain_name; l.in.connect_handle = &p_handle; l.in.domain_name = &name; @@ -826,23 +556,23 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru talloc_free(tmp_ctx); return status; } - domain_sid = l.out.sid; + connect_with_info->out.domain_sid = l.out.sid; } /* prepare samr_OpenDomain */ ZERO_STRUCT(d_handle); od.in.connect_handle = &p_handle; od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; - od.in.sid = domain_sid; + od.in.sid = connect_with_info->out.domain_sid; od.out.domain_handle = &d_handle; - /* 4. do a samr_OpenDomain to get a domain handle */ + /* do a samr_OpenDomain to get a domain handle */ status = dcerpc_samr_OpenDomain(samr_pipe, tmp_ctx, &od); if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, - "samr_OpenDomain for [%s] failed: %s", - r->in.domain_name, - nt_errstr(status)); + "samr_OpenDomain for [%s] failed: %s", + dom_sid_string(tmp_ctx, connect_with_info->out.domain_sid), + nt_errstr(status)); talloc_free(tmp_ctx); return status; } @@ -858,17 +588,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru cu.out.rid = &rid; cu.out.access_granted = &access_granted; - /* 4. do a samr_CreateUser2 to get an account handle, or an error */ + /* do a samr_CreateUser2 to get an account handle, or an error */ cu_status = dcerpc_samr_CreateUser2(samr_pipe, tmp_ctx, &cu); status = cu_status; - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "samr_CreateUser2 for [%s] failed: %s\n", - r->in.domain_name, nt_errstr(status)); - talloc_free(tmp_ctx); - return status; - - } else if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { /* prepare samr_LookupNames */ ln.in.domain_handle = &d_handle; ln.in.num_names = 1; @@ -894,7 +617,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru /* check if we got one RID for the user */ if (ln.out.rids.count != 1) { r->out.error_string = talloc_asprintf(mem_ctx, - "samr_LookupNames for [%s] returns %d RIDs\n", + "samr_LookupNames for [%s] returns %d RIDs", r->in.account_name, ln.out.rids.count); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; @@ -937,16 +660,20 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru /* &cu filled in above */ status = dcerpc_samr_CreateUser2(samr_pipe, tmp_ctx, &cu); - if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) { + if (!NT_STATUS_IS_OK(status)) { r->out.error_string = talloc_asprintf(mem_ctx, - "samr_CreateUser2 (recreate) for [%s] failed: %s\n", - r->in.domain_name, nt_errstr(status)); + "samr_CreateUser2 (recreate) for [%s] failed: %s", + r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; } - DEBUG(0, ("Recreated account in domain %s\n", domain_name)); - } + } else if (!NT_STATUS_IS_OK(status)) { + r->out.error_string = talloc_asprintf(mem_ctx, + "samr_CreateUser2 for [%s] failed: %s", + r->in.account_name, nt_errstr(status)); + talloc_free(tmp_ctx); + return status; } /* prepare samr_QueryUserInfo (get flags) */ @@ -967,7 +694,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru status = NT_STATUS_INVALID_PARAMETER; r->out.error_string = talloc_asprintf(mem_ctx, - "samr_QueryUserInfo failed to return qui.out.info for [%s]: %s\n", + "samr_QueryUserInfo failed to return qui.out.info for [%s]: %s", r->in.account_name, nt_errstr(status)); talloc_free(tmp_ctx); return status; @@ -1009,7 +736,9 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru /* We created a new user, but they didn't come out the right type?!? */ r->out.error_string = talloc_asprintf(mem_ctx, - "We asked to create a new machine account (%s) of type %s, but we got an account of type %s. This is unexpected. Perhaps delete the account and try again.\n", + "We asked to create a new machine account (%s) of type %s, " + "but we got an account of type %s. This is unexpected. " + "Perhaps delete the account and try again.", r->in.account_name, new_account_type, old_account_type); talloc_free(tmp_ctx); return NT_STATUS_INVALID_PARAMETER; @@ -1019,8 +748,10 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru /* TODO: We should allow a --force option to override, and redo this from the top setting r.in.recreate_account */ r->out.error_string = talloc_asprintf(mem_ctx, - "The machine account (%s) already exists in the domain %s, but is a %s. You asked to join as a %s. Please delete the account and try again.\n", - r->in.account_name, domain_name, old_account_type, new_account_type); + "The machine account (%s) already exists in the domain %s, " + "but is a %s. You asked to join as a %s. Please delete " + "the account and try again.", + r->in.account_name, connect_with_info->out.domain_name, old_account_type, new_account_type); talloc_free(tmp_ctx); return NT_STATUS_USER_EXISTS; } @@ -1028,7 +759,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru acct_flags = qui.out.info->info16.acct_flags; } - acct_flags = (acct_flags & ~ACB_DISABLED); + acct_flags = (acct_flags & ~(ACB_DISABLED|ACB_PWNOTREQ)); /* Find out what password policy this user has */ pwp.in.user_handle = u_handle; @@ -1042,11 +773,18 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru password_str = generate_random_str(tmp_ctx, MAX(8, policy_min_pw_len)); + /* set full_name and reset flags */ + ZERO_STRUCT(u_info21); + u_info21.full_name.string = r->in.account_name; + u_info21.acct_flags = acct_flags; + u_info21.fields_present = SAMR_FIELD_FULL_NAME | SAMR_FIELD_ACCT_FLAGS; + r2.samr_handle.level = LIBNET_SET_PASSWORD_SAMR_HANDLE; r2.samr_handle.in.account_name = r->in.account_name; r2.samr_handle.in.newpassword = password_str; r2.samr_handle.in.user_handle = u_handle; r2.samr_handle.in.dcerpc_pipe = samr_pipe; + r2.samr_handle.in.info21 = &u_info21; status = libnet_SetPassword(ctx, tmp_ctx, &r2); if (!NT_STATUS_IS_OK(status)) { @@ -1055,52 +793,31 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru return status; } - /* reset flags (if required) */ - if (acct_flags != qui.out.info->info16.acct_flags) { - ZERO_STRUCT(u_info); - u_info.info16.acct_flags = acct_flags; - - sui.in.user_handle = u_handle; - sui.in.info = &u_info; - sui.in.level = 16; - - dcerpc_samr_SetUserInfo(samr_pipe, tmp_ctx, &sui); - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, - "samr_SetUserInfo for [%s] failed to remove ACB_DISABLED flag: %s", - r->in.account_name, - nt_errstr(status)); - talloc_free(tmp_ctx); - return status; - } - } - - account_sid = dom_sid_add_rid(mem_ctx, domain_sid, rid); + account_sid = dom_sid_add_rid(mem_ctx, connect_with_info->out.domain_sid, rid); if (!account_sid) { r->out.error_string = NULL; talloc_free(tmp_ctx); return NT_STATUS_NO_MEMORY; } + /* Finish out by pushing various bits of status data out for the caller to use */ r->out.join_password = password_str; - talloc_steal(mem_ctx, password_str); + talloc_steal(mem_ctx, r->out.join_password); - r->out.domain_sid = domain_sid; - talloc_steal(mem_ctx, domain_sid); + r->out.domain_sid = connect_with_info->out.domain_sid; + talloc_steal(mem_ctx, r->out.domain_sid); r->out.account_sid = account_sid; - talloc_steal(mem_ctx, account_sid); - - r->out.domain_name = domain_name; - talloc_steal(mem_ctx, domain_name); - r->out.realm = realm; - talloc_steal(mem_ctx, realm); - r->out.lsa_pipe = lsa_pipe; - talloc_steal(mem_ctx, lsa_pipe); + talloc_steal(mem_ctx, r->out.account_sid); + + r->out.domain_name = connect_with_info->out.domain_name; + talloc_steal(mem_ctx, r->out.domain_name); + r->out.realm = connect_with_info->out.realm; + talloc_steal(mem_ctx, r->out.realm); r->out.samr_pipe = samr_pipe; talloc_steal(mem_ctx, samr_pipe); - r->out.samr_binding = samr_binding; - talloc_steal(mem_ctx, samr_binding); + r->out.samr_binding = samr_pipe->binding; + talloc_steal(mem_ctx, r->out.samr_binding); r->out.user_handle = u_handle; talloc_steal(mem_ctx, u_handle); r->out.error_string = r2.samr_handle.out.error_string; @@ -1111,7 +828,7 @@ NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, stru /* Now, if it was AD, then we want to start looking changing a * few more things. Otherwise, we are done. */ - if (realm) { + if (r->out.realm) { status = libnet_JoinADSDomain(ctx, r); return status; } @@ -1128,7 +845,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, struct libnet_JoinDomain *r2; int ret, rtn; struct ldb_context *ldb; - const struct ldb_dn *base_dn; + struct ldb_dn *base_dn; struct ldb_message **msgs, *msg; const char *sct; const char * const attrs[] = { @@ -1136,12 +853,13 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, "secret", "priorSecret", "priorChanged", + "krb5Keytab", + "privateKeytab", NULL }; uint32_t acct_type = 0; const char *account_name; const char *netbios_name; - char *filter; r->out.error_string = NULL; @@ -1157,9 +875,9 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, return NT_STATUS_NO_MEMORY; } - if (r->in.secure_channel_type == SEC_CHAN_BDC) { + if (r->in.join_type == SEC_CHAN_BDC) { acct_type = ACB_SVRTRUST; - } else if (r->in.secure_channel_type == SEC_CHAN_WKSTA) { + } else if (r->in.join_type == SEC_CHAN_WKSTA) { acct_type = ACB_WSTRUST; } else { r->out.error_string = NULL; @@ -1167,10 +885,10 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, return NT_STATUS_INVALID_PARAMETER; } - if ((r->in.netbios_name != NULL) && (r->in.level != LIBNET_JOIN_AUTOMATIC)) { + if (r->in.netbios_name != NULL) { netbios_name = r->in.netbios_name; } else { - netbios_name = talloc_asprintf(tmp_mem, "%s", lp_netbios_name()); + netbios_name = talloc_reference(tmp_mem, lp_netbios_name()); if (!netbios_name) { r->out.error_string = NULL; talloc_free(tmp_mem); @@ -1193,7 +911,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, if (!ldb) { r->out.error_string = talloc_asprintf(mem_ctx, - "Could not open secrets database\n"); + "Could not open secrets database"); talloc_free(tmp_mem); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -1218,7 +936,7 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, /* * now prepare the record for secrets.ldb */ - sct = talloc_asprintf(tmp_mem, "%d", r->in.secure_channel_type); + sct = talloc_asprintf(tmp_mem, "%d", r->in.join_type); if (!sct) { r->out.error_string = NULL; talloc_free(tmp_mem); @@ -1232,15 +950,15 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, return NT_STATUS_NO_MEMORY; } - base_dn = ldb_dn_explode(tmp_mem, "cn=Primary Domains"); + 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_build_child(tmp_mem, "flatname", r2->out.domain_name, base_dn); - if (!msg->dn) { + msg->dn = ldb_dn_copy(tmp_mem, base_dn); + if ( ! ldb_dn_add_child_fmt(msg->dn, "flatname=%s", r2->out.domain_name)) { r->out.error_string = NULL; talloc_free(tmp_mem); return NT_STATUS_NO_MEMORY; @@ -1328,6 +1046,12 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, "(|" SECRETS_PRIMARY_DOMAIN_FILTER "(realm=%s))", r2->out.domain_name, r2->out.realm); if (ret == 0) { + rtn = samdb_msg_set_string(ldb, tmp_mem, msg, "secretsKeytab", "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, @@ -1336,6 +1060,8 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, talloc_free(tmp_mem); return NT_STATUS_INTERNAL_DB_CORRUPTION; } else { + const struct ldb_val *private_keytab; + const struct ldb_val *krb5_keytab; const struct ldb_val *prior_secret; const struct ldb_val *prior_modified_time; int i; @@ -1385,57 +1111,52 @@ static NTSTATUS libnet_Join_primary_domain(struct libnet_context *ctx, 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_keytab = ldb_msg_find_ldb_val(msgs[0], "krb5Keytab"); + if (krb5_keytab) { + rtn = samdb_msg_set_value(ldb, tmp_mem, msg, "krb5Keytab", krb5_keytab); + if (rtn == -1) { + r->out.error_string = NULL; + talloc_free(tmp_mem); + return NT_STATUS_NO_MEMORY; + } + } } /* create the secret */ ret = samdb_add(ldb, tmp_mem, msg); if (ret != 0) { - r->out.error_string = talloc_asprintf(mem_ctx, "Failed to create secret record %s\n", - ldb_dn_linearize(ldb, msg->dn)); + 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; } - if (r2->out.realm) { - struct cli_credentials *creds; - /* Make a credentials structure from it */ - creds = cli_credentials_init(mem_ctx); - if (!creds) { - r->out.error_string = NULL; - talloc_free(tmp_mem); - return NT_STATUS_NO_MEMORY; - } - cli_credentials_set_conf(creds); - filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_linearize(mem_ctx, msg->dn)); - status = cli_credentials_set_secrets(creds, NULL, filter); - if (!NT_STATUS_IS_OK(status)) { - r->out.error_string = talloc_asprintf(mem_ctx, "Failed to read secrets for keytab update for %s\n", - filter); - talloc_free(tmp_mem); - return status; - } - ret = cli_credentials_update_keytab(creds); - if (ret != 0) { - r->out.error_string = talloc_asprintf(mem_ctx, "Failed to update keytab for %s\n", - filter); - talloc_free(tmp_mem); - return NT_STATUS_UNSUCCESSFUL; - } - } - /* 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); r->out.domain_sid = r2->out.domain_sid; talloc_steal(mem_ctx, r2->out.domain_sid); + r->out.domain_name = r2->out.domain_name; + talloc_steal(mem_ctx, r2->out.domain_name); talloc_free(tmp_mem); return NT_STATUS_OK; } NTSTATUS libnet_Join(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_Join *r) { - switch (r->in.secure_channel_type) { + switch (r->in.join_type) { case SEC_CHAN_WKSTA: return libnet_Join_primary_domain(ctx, mem_ctx, r); case SEC_CHAN_BDC: @@ -1445,9 +1166,7 @@ NTSTATUS libnet_Join(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct lib } r->out.error_string = talloc_asprintf(mem_ctx, - "Invalid secure channel type specified (%08X) attempting to join domain %s", - r->in.secure_channel_type, r->in.domain_name); + "Invalid join type specified (%08X) attempting to join domain %s", + r->in.join_type, r->in.domain_name); return NT_STATUS_INVALID_PARAMETER; } - -