関数 | |
int | net_rpc_join_ok (const char *domain, const char *server, struct in_addr *ip) |
confirm that a domain join is still valid | |
int | net_rpc_join_newstyle (int argc, const char **argv) |
Join a domain using the administrator username and password | |
int | net_rpc_testjoin (int argc, const char **argv) |
check that a join is OK |
int net_rpc_join_ok | ( | const char * | domain, | |
const char * | server, | |||
struct in_addr * | ip | |||
) |
confirm that a domain join is still valid
net_rpc_join.c の 44 行で定義されています。
参照先 cli・cli_rpc_pipe_open_schannel_with_key()・cli_shutdown()・rpc_pipe_client::dc・cli_state::desthost・get_schannel_session_key()・net_make_ipc_connection_ex()・net_use_machine_account()・nt_errstr()・PIPE_AUTH_LEVEL_PRIVACY・SEC_ADS.
参照元 net_ads_join()・net_rpc_join_newstyle()・net_rpc_testjoin().
00045 { 00046 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; 00047 enum security_types sec; 00048 unsigned int conn_flags = NET_FLAGS_PDC | NET_FLAGS_ANONYMOUS; 00049 struct cli_state *cli = NULL; 00050 struct rpc_pipe_client *pipe_hnd = NULL; 00051 struct rpc_pipe_client *netlogon_pipe = NULL; 00052 NTSTATUS ntret = NT_STATUS_UNSUCCESSFUL; 00053 00054 sec = (enum security_types)lp_security(); 00055 00056 if (sec == SEC_ADS) { 00057 /* Connect to IPC$ using machine account's credentials. We don't use anonymous 00058 connection here, as it may be denied by server's local policy. */ 00059 net_use_machine_account(); 00060 00061 } 00062 00063 /* Connect to remote machine */ 00064 if (!(cli = net_make_ipc_connection_ex(domain, server, ip, conn_flags))) { 00065 return -1; 00066 } 00067 00068 /* Setup the creds as though we're going to do schannel... */ 00069 netlogon_pipe = get_schannel_session_key(cli, domain, &neg_flags, &ntret); 00070 00071 /* We return NT_STATUS_INVALID_NETWORK_RESPONSE if the server is refusing 00072 to negotiate schannel, but the creds were set up ok. That'll have to do. */ 00073 00074 if (!netlogon_pipe) { 00075 if (NT_STATUS_EQUAL(ntret, NT_STATUS_INVALID_NETWORK_RESPONSE)) { 00076 cli_shutdown(cli); 00077 return 0; 00078 } else { 00079 DEBUG(0,("net_rpc_join_ok: failed to get schannel session " 00080 "key from server %s for domain %s. Error was %s\n", 00081 cli->desthost, domain, nt_errstr(ntret) )); 00082 cli_shutdown(cli); 00083 return -1; 00084 } 00085 } 00086 00087 /* Only do the rest of the schannel test if the client is allowed to do this. */ 00088 if (!lp_client_schannel()) { 00089 cli_shutdown(cli); 00090 /* We're good... */ 00091 return 0; 00092 } 00093 00094 pipe_hnd = cli_rpc_pipe_open_schannel_with_key(cli, PI_NETLOGON, 00095 PIPE_AUTH_LEVEL_PRIVACY, 00096 domain, netlogon_pipe->dc, &ntret); 00097 00098 if (!pipe_hnd) { 00099 DEBUG(0,("net_rpc_join_ok: failed to open schannel session " 00100 "on netlogon pipe to server %s for domain %s. Error was %s\n", 00101 cli->desthost, domain, nt_errstr(ntret) )); 00102 cli_shutdown(cli); 00103 return -1; 00104 } 00105 00106 cli_shutdown(cli); 00107 return 0; 00108 }
int net_rpc_join_newstyle | ( | int | argc, | |
const char ** | argv | |||
) |
Join a domain using the administrator username and password
argc | Standard main() style argc | |
argc | Standard main() style argv. Initial components are already stripped. Currently not used. |
net_rpc_join.c の 120 行で定義されています。
参照先 cli・cli_rpc_pipe_close()・cli_rpc_pipe_open_noauth()・cli_rpc_pipe_open_schannel_with_key()・cli_shutdown()・d_fprintf()・rpc_pipe_client::dc・cli_state::dest_ip・cli_state::desthost・rpc_pipe_client::domain・domain_sid・E_md4hash()・encode_pw_buffer()・flags・fprintf()・generate_random_str()・get_sec_channel_type()・global_myname・sam_userinfo_ctr_info::id16・sam_userinfo_ctr_info::id24・sam_userinfo_ctr_info::info・init_sam_user_info16()・init_sam_user_info24()・cli_state::mem_ctx・net_make_ipc_connection()・net_rpc_join_ok()・nt_errstr()・PIPE_AUTH_LEVEL_PRIVACY・printf()・result・rpccli_lsa_close()・rpccli_lsa_open_policy()・rpccli_lsa_query_info_policy()・rpccli_netlogon_setup_creds()・rpccli_samr_close()・rpccli_samr_connect()・rpccli_samr_create_dom_user()・rpccli_samr_lookup_names()・rpccli_samr_open_domain()・rpccli_samr_open_user()・rpccli_samr_set_userinfo()・rpccli_samr_set_userinfo2()・SEC_CHAN_BDC・SEC_CHAN_DOMAIN・SEC_CHAN_WKSTA・secrets_store_domain_sid()・secrets_store_machine_password()・SID_NAME_USER・strlower_m()・strupper_m()・sam_userinfo_ctr_info::switch_value・talloc_asprintf()・talloc_init()・cli_state::user_session_key.
参照元 net_rpc_join().
00121 { 00122 00123 /* libsmb variables */ 00124 00125 struct cli_state *cli; 00126 TALLOC_CTX *mem_ctx; 00127 uint32 acb_info = ACB_WSTRUST; 00128 uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; 00129 uint32 sec_channel_type; 00130 struct rpc_pipe_client *pipe_hnd = NULL; 00131 00132 /* rpc variables */ 00133 00134 POLICY_HND lsa_pol, sam_pol, domain_pol, user_pol; 00135 DOM_SID *domain_sid; 00136 uint32 user_rid; 00137 00138 /* Password stuff */ 00139 00140 char *clear_trust_password = NULL; 00141 uchar pwbuf[516]; 00142 SAM_USERINFO_CTR ctr; 00143 SAM_USER_INFO_24 p24; 00144 SAM_USER_INFO_16 p16; 00145 uchar md4_trust_password[16]; 00146 00147 /* Misc */ 00148 00149 NTSTATUS result; 00150 int retval = 1; 00151 char *domain = NULL; 00152 uint32 num_rids, *name_types, *user_rids; 00153 uint32 flags = 0x3e8; 00154 char *acct_name; 00155 const char *const_acct_name; 00156 uint32 acct_flags=0; 00157 00158 /* check what type of join */ 00159 if (argc >= 0) { 00160 sec_channel_type = get_sec_channel_type(argv[0]); 00161 } else { 00162 sec_channel_type = get_sec_channel_type(NULL); 00163 } 00164 00165 switch (sec_channel_type) { 00166 case SEC_CHAN_WKSTA: 00167 acb_info = ACB_WSTRUST; 00168 break; 00169 case SEC_CHAN_BDC: 00170 acb_info = ACB_SVRTRUST; 00171 break; 00172 #if 0 00173 case SEC_CHAN_DOMAIN: 00174 acb_info = ACB_DOMTRUST; 00175 break; 00176 #endif 00177 } 00178 00179 /* Make authenticated connection to remote machine */ 00180 00181 if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) 00182 return 1; 00183 00184 if (!(mem_ctx = talloc_init("net_rpc_join_newstyle"))) { 00185 DEBUG(0, ("Could not initialise talloc context\n")); 00186 goto done; 00187 } 00188 00189 /* Fetch domain sid */ 00190 00191 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result); 00192 if (!pipe_hnd) { 00193 DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", 00194 nt_errstr(result) )); 00195 goto done; 00196 } 00197 00198 00199 CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, 00200 SEC_RIGHTS_MAXIMUM_ALLOWED, 00201 &lsa_pol), 00202 "error opening lsa policy handle"); 00203 00204 CHECK_RPC_ERR(rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &lsa_pol, 00205 5, &domain, &domain_sid), 00206 "error querying info policy"); 00207 00208 rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol); 00209 cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */ 00210 00211 /* Bail out if domain didn't get set. */ 00212 if (!domain) { 00213 DEBUG(0, ("Could not get domain name.\n")); 00214 goto done; 00215 } 00216 00217 /* Create domain user */ 00218 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result); 00219 if (!pipe_hnd) { 00220 DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", 00221 nt_errstr(result) )); 00222 goto done; 00223 } 00224 00225 CHECK_RPC_ERR(rpccli_samr_connect(pipe_hnd, mem_ctx, 00226 SEC_RIGHTS_MAXIMUM_ALLOWED, 00227 &sam_pol), 00228 "could not connect to SAM database"); 00229 00230 00231 CHECK_RPC_ERR(rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol, 00232 SEC_RIGHTS_MAXIMUM_ALLOWED, 00233 domain_sid, &domain_pol), 00234 "could not open domain"); 00235 00236 /* Create domain user */ 00237 if ((acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname())) == NULL) { 00238 result = NT_STATUS_NO_MEMORY; 00239 goto done; 00240 } 00241 strlower_m(acct_name); 00242 const_acct_name = acct_name; 00243 00244 acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE | 00245 SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC | 00246 SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR | 00247 SAMR_USER_SETATTR; 00248 DEBUG(10, ("Creating account with flags: %d\n",acct_flags)); 00249 result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, 00250 acct_name, acb_info, 00251 acct_flags, &user_pol, 00252 &user_rid); 00253 00254 if (!NT_STATUS_IS_OK(result) && 00255 !NT_STATUS_EQUAL(result, NT_STATUS_USER_EXISTS)) { 00256 d_fprintf(stderr, "Creation of workstation account failed\n"); 00257 00258 /* If NT_STATUS_ACCESS_DENIED then we have a valid 00259 username/password combo but the user does not have 00260 administrator access. */ 00261 00262 if (NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED)) 00263 d_fprintf(stderr, "User specified does not have administrator privileges\n"); 00264 00265 goto done; 00266 } 00267 00268 /* We *must* do this.... don't ask... */ 00269 00270 if (NT_STATUS_IS_OK(result)) { 00271 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); 00272 } 00273 00274 CHECK_RPC_ERR_DEBUG(rpccli_samr_lookup_names(pipe_hnd, mem_ctx, 00275 &domain_pol, flags, 00276 1, &const_acct_name, 00277 &num_rids, 00278 &user_rids, &name_types), 00279 ("error looking up rid for user %s: %s\n", 00280 acct_name, nt_errstr(result))); 00281 00282 if (name_types[0] != SID_NAME_USER) { 00283 DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0])); 00284 goto done; 00285 } 00286 00287 user_rid = user_rids[0]; 00288 00289 /* Open handle on user */ 00290 00291 CHECK_RPC_ERR_DEBUG( 00292 rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, 00293 SEC_RIGHTS_MAXIMUM_ALLOWED, 00294 user_rid, &user_pol), 00295 ("could not re-open existing user %s: %s\n", 00296 acct_name, nt_errstr(result))); 00297 00298 /* Create a random machine account password */ 00299 00300 { 00301 char *str; 00302 str = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH); 00303 clear_trust_password = SMB_STRDUP(str); 00304 E_md4hash(clear_trust_password, md4_trust_password); 00305 } 00306 00307 encode_pw_buffer(pwbuf, clear_trust_password, STR_UNICODE); 00308 00309 /* Set password on machine account */ 00310 00311 ZERO_STRUCT(ctr); 00312 ZERO_STRUCT(p24); 00313 00314 init_sam_user_info24(&p24, (char *)pwbuf,24); 00315 00316 ctr.switch_value = 24; 00317 ctr.info.id24 = &p24; 00318 00319 CHECK_RPC_ERR(rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, 00320 &cli->user_session_key, &ctr), 00321 "error setting trust account password"); 00322 00323 /* Why do we have to try to (re-)set the ACB to be the same as what 00324 we passed in the samr_create_dom_user() call? When a NT 00325 workstation is joined to a domain by an administrator the 00326 acb_info is set to 0x80. For a normal user with "Add 00327 workstations to the domain" rights the acb_info is 0x84. I'm 00328 not sure whether it is supposed to make a difference or not. NT 00329 seems to cope with either value so don't bomb out if the set 00330 userinfo2 level 0x10 fails. -tpot */ 00331 00332 ZERO_STRUCT(ctr); 00333 ctr.switch_value = 16; 00334 ctr.info.id16 = &p16; 00335 00336 init_sam_user_info16(&p16, acb_info); 00337 00338 /* Ignoring the return value is necessary for joining a domain 00339 as a normal user with "Add workstation to domain" privilege. */ 00340 00341 result = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, 00342 &cli->user_session_key, &ctr); 00343 00344 rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); 00345 cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */ 00346 00347 /* Now check the whole process from top-to-bottom */ 00348 00349 pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result); 00350 if (!pipe_hnd) { 00351 DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", 00352 nt_errstr(result) )); 00353 goto done; 00354 } 00355 00356 result = rpccli_netlogon_setup_creds(pipe_hnd, 00357 cli->desthost, /* server name */ 00358 domain, /* domain */ 00359 global_myname(), /* client name */ 00360 global_myname(), /* machine account name */ 00361 md4_trust_password, 00362 sec_channel_type, 00363 &neg_flags); 00364 00365 if (!NT_STATUS_IS_OK(result)) { 00366 DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n", 00367 nt_errstr(result))); 00368 00369 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && 00370 (sec_channel_type == SEC_CHAN_BDC) ) { 00371 d_fprintf(stderr, "Please make sure that no computer account\n" 00372 "named like this machine (%s) exists in the domain\n", 00373 global_myname()); 00374 } 00375 00376 goto done; 00377 } 00378 00379 /* We can only check the schannel connection if the client is allowed 00380 to do this and the server supports it. If not, just assume success 00381 (after all the rpccli_netlogon_setup_creds() succeeded, and we'll 00382 do the same again (setup creds) in net_rpc_join_ok(). JRA. */ 00383 00384 if (lp_client_schannel() && (neg_flags & NETLOGON_NEG_SCHANNEL)) { 00385 struct rpc_pipe_client *netlogon_schannel_pipe = 00386 cli_rpc_pipe_open_schannel_with_key(cli, 00387 PI_NETLOGON, 00388 PIPE_AUTH_LEVEL_PRIVACY, 00389 domain, 00390 pipe_hnd->dc, 00391 &result); 00392 00393 if (!NT_STATUS_IS_OK(result)) { 00394 DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n", 00395 nt_errstr(result))); 00396 00397 if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && 00398 (sec_channel_type == SEC_CHAN_BDC) ) { 00399 d_fprintf(stderr, "Please make sure that no computer account\n" 00400 "named like this machine (%s) exists in the domain\n", 00401 global_myname()); 00402 } 00403 00404 goto done; 00405 } 00406 cli_rpc_pipe_close(netlogon_schannel_pipe); 00407 } 00408 00409 cli_rpc_pipe_close(pipe_hnd); 00410 00411 /* Now store the secret in the secrets database */ 00412 00413 strupper_m(domain); 00414 00415 if (!secrets_store_domain_sid(domain, domain_sid)) { 00416 DEBUG(0, ("error storing domain sid for %s\n", domain)); 00417 goto done; 00418 } 00419 00420 if (!secrets_store_machine_password(clear_trust_password, domain, sec_channel_type)) { 00421 DEBUG(0, ("error storing plaintext domain secrets for %s\n", domain)); 00422 } 00423 00424 /* double-check, connection from scratch */ 00425 retval = net_rpc_join_ok(domain, cli->desthost, &cli->dest_ip); 00426 00427 done: 00428 00429 /* Display success or failure */ 00430 00431 if (domain) { 00432 if (retval != 0) { 00433 fprintf(stderr,"Unable to join domain %s.\n",domain); 00434 } else { 00435 printf("Joined domain %s.\n",domain); 00436 } 00437 } 00438 00439 cli_shutdown(cli); 00440 00441 SAFE_FREE(clear_trust_password); 00442 00443 return retval; 00444 }
int net_rpc_testjoin | ( | int | argc, | |
const char ** | argv | |||
) |
check that a join is OK
net_rpc_join.c の 452 行で定義されています。
参照先 rpc_pipe_client::domain・fprintf()・net_rpc_join_ok()・opt_target_workgroup・printf()・smb_xstrdup().
参照元 net_rpc().
00453 { 00454 char *domain = smb_xstrdup(opt_target_workgroup); 00455 00456 /* Display success or failure */ 00457 if (net_rpc_join_ok(domain, NULL, NULL) != 0) { 00458 fprintf(stderr,"Join to domain '%s' is not valid\n",domain); 00459 free(domain); 00460 return -1; 00461 } 00462 00463 printf("Join to '%s' is OK\n",domain); 00464 free(domain); 00465 return 0; 00466 }