/** * The challenge from the target server, when operating in security=server **/ static NTSTATUS server_get_challenge(struct auth_method_context *ctx, TALLOC_CTX *mem_ctx, uint8_t chal[8]) { struct smb_composite_connect io; struct smbcli_options smb_options; const char **host_list; NTSTATUS status; /* Make a connection to the target server, found by 'password server' in smb.conf */ lp_smbcli_options(ctx->auth_ctx->lp_ctx, &smb_options); /* Make a negprot, WITHOUT SPNEGO, so we get a challenge nice an easy */ io.in.options.use_spnego = false; /* Hope we don't get * (the default), as this won't work... */ host_list = lp_passwordserver(ctx->auth_ctx->lp_ctx); if (!host_list) { return NT_STATUS_INTERNAL_ERROR; } io.in.dest_host = host_list[0]; if (strequal(io.in.dest_host, "*")) { return NT_STATUS_INTERNAL_ERROR; } io.in.dest_ports = lp_smb_ports(ctx->auth_ctx->lp_ctx); io.in.socket_options = lp_socket_options(ctx->auth_ctx->lp_ctx); io.in.gensec_settings = lp_gensec_settings(mem_ctx, ctx->auth_ctx->lp_ctx); io.in.called_name = strupper_talloc(mem_ctx, io.in.dest_host); /* We don't want to get as far as the session setup */ io.in.credentials = cli_credentials_init_anon(mem_ctx); cli_credentials_set_workstation(io.in.credentials, lp_netbios_name(ctx->auth_ctx->lp_ctx), CRED_SPECIFIED); io.in.service = NULL; io.in.workgroup = ""; /* only used with SPNEGO, disabled above */ io.in.options = smb_options; io.in.iconv_convenience = lp_iconv_convenience(ctx->auth_ctx->lp_ctx); lp_smbcli_session_options(ctx->auth_ctx->lp_ctx, &io.in.session_options); status = smb_composite_connect(&io, mem_ctx, lp_resolve_context(ctx->auth_ctx->lp_ctx), ctx->auth_ctx->event_ctx); NT_STATUS_NOT_OK_RETURN(status); if (io.out.tree->session->transport->negotiate.secblob.length != 8) { return NT_STATUS_INTERNAL_ERROR; } memcpy(chal, io.out.tree->session->transport->negotiate.secblob.data, 8); ctx->private_data = talloc_steal(ctx, io.out.tree->session); return NT_STATUS_OK; }
static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) { struct cli_state *cli = NULL; char *desthost = NULL; struct sockaddr_storage dest_ss; const char *p; char *pserver = NULL; bool connected_ok = False; struct named_mutex *mutex = NULL; NTSTATUS status; pserver = talloc_strdup(mem_ctx, lp_passwordserver()); p = pserver; while(next_token_talloc(mem_ctx, &p, &desthost, LIST_SEP)) { desthost = talloc_sub_basic(mem_ctx, current_user_info.smb_name, current_user_info.domain, desthost); if (!desthost) { return NULL; } strupper_m(desthost); if (strequal(desthost, myhostname())) { DEBUG(1,("Password server loop - disabling " "password server %s\n", desthost)); continue; } if(!resolve_name( desthost, &dest_ss, 0x20, false)) { DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); continue; } if (ismyaddr((struct sockaddr *)(void *)&dest_ss)) { DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); continue; } /* we use a mutex to prevent two connections at once - when a Win2k PDC get two connections where one hasn't completed a session setup yet it will send a TCP reset to the first connection (tridge) */ mutex = grab_named_mutex(talloc_tos(), desthost, 10); if (mutex == NULL) { return NULL; } status = cli_connect_nb(desthost, &dest_ss, 0, 0x20, lp_netbios_name(), Undefined, &cli); if (NT_STATUS_IS_OK(status)) { DEBUG(3,("connected to password server %s\n",desthost)); connected_ok = True; break; } DEBUG(10,("server_cryptkey: failed to connect to server %s. Error %s\n", desthost, nt_errstr(status) )); TALLOC_FREE(mutex); } if (!connected_ok) { DEBUG(0,("password server not available\n")); return NULL; } /* security = server just can't function with spnego */ cli->use_spnego = False; DEBUG(3,("got session\n")); status = cli_negprot(cli); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(mutex); DEBUG(1, ("%s rejected the negprot: %s\n", desthost, nt_errstr(status))); cli_shutdown(cli); return NULL; } if (cli->protocol < PROTOCOL_LANMAN2 || !(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) { TALLOC_FREE(mutex); DEBUG(1,("%s isn't in user level security mode\n",desthost)); cli_shutdown(cli); return NULL; } /* Get the first session setup done quickly, to avoid silly Win2k bugs. (The next connection to the server will kill this one... */ status = cli_session_setup(cli, "", "", 0, "", 0, ""); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(mutex); DEBUG(0,("%s rejected the initial session setup (%s)\n", desthost, nt_errstr(status))); cli_shutdown(cli); return NULL; } TALLOC_FREE(mutex); DEBUG(3,("password server OK\n")); return cli; }
static struct cli_state *server_cryptkey(TALLOC_CTX *mem_ctx) { struct cli_state *cli = NULL; fstring desthost; struct in_addr dest_ip; const char *p; char *pserver; BOOL connected_ok = False; if (!(cli = cli_initialise())) return NULL; /* security = server just can't function with spnego */ cli->use_spnego = False; pserver = talloc_strdup(mem_ctx, lp_passwordserver()); p = pserver; while(next_token( &p, desthost, LIST_SEP, sizeof(desthost))) { standard_sub_basic(current_user_info.smb_name, current_user_info.domain, desthost, sizeof(desthost)); strupper_m(desthost); if(!resolve_name( desthost, &dest_ip, 0x20)) { DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",desthost)); continue; } if (ismyip(dest_ip)) { DEBUG(1,("Password server loop - disabling password server %s\n",desthost)); continue; } /* we use a mutex to prevent two connections at once - when a Win2k PDC get two connections where one hasn't completed a session setup yet it will send a TCP reset to the first connection (tridge) */ if (!grab_server_mutex(desthost)) { return NULL; } if (cli_connect(cli, desthost, &dest_ip)) { DEBUG(3,("connected to password server %s\n",desthost)); connected_ok = True; break; } } if (!connected_ok) { release_server_mutex(); DEBUG(0,("password server not available\n")); cli_shutdown(cli); return NULL; } if (!attempt_netbios_session_request(&cli, global_myname(), desthost, &dest_ip)) { release_server_mutex(); DEBUG(1,("password server fails session request\n")); cli_shutdown(cli); return NULL; } if (strequal(desthost,myhostname())) { exit_server_cleanly("Password server loop!"); } DEBUG(3,("got session\n")); if (!cli_negprot(cli)) { DEBUG(1,("%s rejected the negprot\n",desthost)); release_server_mutex(); cli_shutdown(cli); return NULL; } if (cli->protocol < PROTOCOL_LANMAN2 || !(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) { DEBUG(1,("%s isn't in user level security mode\n",desthost)); release_server_mutex(); cli_shutdown(cli); return NULL; } /* Get the first session setup done quickly, to avoid silly Win2k bugs. (The next connection to the server will kill this one... */ if (!NT_STATUS_IS_OK(cli_session_setup(cli, "", "", 0, "", 0, ""))) { DEBUG(0,("%s rejected the initial session setup (%s)\n", desthost, cli_errstr(cli))); release_server_mutex(); cli_shutdown(cli); return NULL; } release_server_mutex(); DEBUG(3,("password server OK\n")); return cli; }
/**************************************************************************** support for server level security ****************************************************************************/ struct cli_state *server_cryptkey(void) { fstring desthost; struct in_addr dest_ip; extern fstring local_machine; char *p; if (!cli_initialise(&cli)) return NULL; for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) { fstrcpy(desthost,p); standard_sub_basic(desthost); strupper(desthost); if(!resolve_name( desthost, &dest_ip)) { DEBUG(1,("server_cryptkey: Can't resolve address for %s\n",p)); continue; } if (ismyip(dest_ip)) { DEBUG(1,("Password server loop - disabling password server %s\n",p)); continue; } if (cli_connect(&cli, desthost, &dest_ip)) { DEBUG(3,("connected to password server %s\n",p)); break; } } if (!p) { DEBUG(1,("password server not available\n")); cli_shutdown(&cli); return NULL; } if (!cli_session_request(&cli, desthost, 0x20, local_machine)) { DEBUG(1,("%s rejected the session\n",desthost)); cli_shutdown(&cli); return NULL; } DEBUG(3,("got session\n")); if (!cli_negprot(&cli)) { DEBUG(1,("%s rejected the negprot\n",desthost)); cli_shutdown(&cli); return NULL; } if (cli.protocol < PROTOCOL_LANMAN2 || !(cli.sec_mode & 1)) { DEBUG(1,("%s isn't in user level security mode\n",desthost)); cli_shutdown(&cli); return NULL; } DEBUG(3,("password server OK\n")); return &cli; }
static struct wkssvc_NetWkstaEnumUsersCtr1 *create_enum_users1( TALLOC_CTX *mem_ctx) { struct wkssvc_NetWkstaEnumUsersCtr1 *ctr1; char **users; struct dom_usr *dom_users; const char *pwd_server; char *pwd_tmp; int i, j, num_users, num_dom_users; ctr1 = talloc(mem_ctx, struct wkssvc_NetWkstaEnumUsersCtr1); if (ctr1 == NULL) { return NULL; } users = get_logged_on_userlist(talloc_tos()); if (users == NULL && errno != 0) { DEBUG(1,("get_logged_on_userlist error %d: %s\n", errno, strerror(errno))); TALLOC_FREE(ctr1); return NULL; } num_users = talloc_array_length(users); dom_users = get_domain_userlist(talloc_tos()); if (dom_users == NULL && errno != 0) { TALLOC_FREE(ctr1); TALLOC_FREE(users); return NULL; } num_dom_users = talloc_array_length(dom_users); ctr1->user1 = talloc_array(ctr1, struct wkssvc_NetrWkstaUserInfo1, num_users+num_dom_users); if (ctr1->user1 == NULL) { TALLOC_FREE(ctr1); TALLOC_FREE(users); TALLOC_FREE(dom_users); return NULL; } pwd_server = ""; if ((pwd_tmp = talloc_strdup(ctr1->user1, lp_passwordserver()))) { /* The configured password server is a full DNS name but * for the logon server we need to return just the first * component (machine name) of it in upper-case */ char *p = strchr(pwd_tmp, '.'); if (p) { *p = '\0'; } else { p = pwd_tmp + strlen(pwd_tmp); } while (--p >= pwd_tmp) { *p = toupper(*p); } pwd_server = pwd_tmp; } /* Put in local users first */ for (i=0; i<num_users; i++) { ctr1->user1[i].user_name = talloc_move(ctr1->user1, &users[i]); /* For a local user the domain name and logon server are * both returned as the local machine's NetBIOS name */ ctr1->user1[i].logon_domain = ctr1->user1[i].logon_server = talloc_asprintf_strupper_m(ctr1->user1, "%s", lp_netbios_name()); ctr1->user1[i].other_domains = NULL; /* Maybe in future? */ } /* Now domain users */ for (j=0; j<num_dom_users; j++) { ctr1->user1[i].user_name = talloc_strdup(ctr1->user1, dom_users[j].name); ctr1->user1[i].logon_domain = talloc_strdup(ctr1->user1, dom_users[j].domain); ctr1->user1[i].logon_server = pwd_server; ctr1->user1[i++].other_domains = NULL; /* Maybe in future? */ } ctr1->entries_read = i; TALLOC_FREE(users); TALLOC_FREE(dom_users); return ctr1; }