/**************************************************************************** display group info ****************************************************************************/ static void display_group_info1(GROUP_INFO1 *info1) { fstring temp; unistr2_to_ascii(temp, &info1->uni_acct_name, sizeof(temp)-1); printf("\tGroup Name:\t%s\n", temp); unistr2_to_ascii(temp, &info1->uni_acct_desc, sizeof(temp)-1); printf("\tDescription:\t%s\n", temp); printf("\tunk1:%d\n", info1->unknown_1); printf("\tNum Members:%d\n", info1->num_members); }
static void display_sam_info_3(SAM_ENTRY3 *e3, SAM_STR3 *s3) { fstring tmp; printf("index: 0x%x ", e3->grp_idx); printf("RID: 0x%x ", e3->rid_grp); printf("attr: 0x%x ", e3->attr); unistr2_to_ascii(tmp, &s3->uni_grp_name, sizeof(tmp)-1); printf("Account: %s\t", tmp); unistr2_to_ascii(tmp, &s3->uni_grp_desc, sizeof(tmp)-1); printf("Name: %s\n", tmp); }
static void display_sam_info_2(SAM_ENTRY2 *e2, SAM_STR2 *s2) { fstring tmp; printf("index: 0x%x ", e2->user_idx); printf("RID: 0x%x ", e2->rid_user); printf("acb: 0x%x ", e2->acb_info); unistr2_to_ascii(tmp, &s2->uni_srv_name, sizeof(tmp)-1); printf("Account: %s\t", tmp); unistr2_to_ascii(tmp, &s2->uni_srv_desc, sizeof(tmp)-1); printf("Name: %s\n", tmp); }
static void display_srv_info_101(SRV_INFO_101 *sv101) { fstring name; fstring comment; unistr2_to_ascii(name, &sv101->uni_name, sizeof(name) - 1); unistr2_to_ascii(comment, &sv101->uni_comment, sizeof(comment) - 1); display_server(name, sv101->srv_type, comment); printf("\tplatform_id :\t%d\n", sv101->platform_id); printf("\tos version :\t%d.%d\n", sv101->ver_major, sv101->ver_minor); printf("\tserver type :\t0x%x\n", sv101->srv_type); }
/**************************************************************************** display group info ****************************************************************************/ static void display_group_info4(GROUP_INFO4 *info4) { fstring desc; unistr2_to_ascii(desc, &info4->uni_acct_desc, sizeof(desc)-1); printf("\tGroup Description:%s\n", desc); }
static void display_sam_info_1(SAM_ENTRY1 *e1, SAM_STR1 *s1) { fstring tmp; printf("index: 0x%x ", e1->user_idx); printf("RID: 0x%x ", e1->rid_user); printf("acb: 0x%x ", e1->acb_info); unistr2_to_ascii(tmp, &s1->uni_acct_name, sizeof(tmp)-1); printf("Account: %s\t", tmp); unistr2_to_ascii(tmp, &s1->uni_full_name, sizeof(tmp)-1); printf("Name: %s\t", tmp); unistr2_to_ascii(tmp, &s1->uni_acct_desc, sizeof(tmp)-1); printf("Desc: %s\n", tmp); }
static void display_srv_info_102(SRV_INFO_102 *sv102) { fstring name; fstring comment; fstring usr_path; unistr2_to_ascii(name, &sv102->uni_name, sizeof(name) - 1); unistr2_to_ascii(comment, &sv102->uni_comment, sizeof(comment) - 1); unistr2_to_ascii(usr_path, &sv102->uni_usr_path, sizeof(usr_path) - 1); display_server(name, sv102->srv_type, comment); printf("\tplatform_id :\t%d\n", sv102->platform_id); printf("\tos version :\t%d.%d\n", sv102->ver_major, sv102->ver_minor); printf("\tusers :\t%x\n", sv102->users); printf("\tdisc, hidden :\t%x, %x\n", sv102->disc, sv102->hidden); printf("\tannounce, delta :\t%d, %d\n", sv102->announce, sv102->ann_delta); printf("\tlicenses :\t%d\n", sv102->licenses); printf("\tuser path :\t%s\n", usr_path); }
static void display_sam_unk_info_2(SAM_UNK_INFO_2 *info2) { fstring name; unistr2_to_ascii(name, &info2->uni_domain, sizeof(name) - 1); printf("Domain:\t%s\n", name); unistr2_to_ascii(name, &info2->uni_server, sizeof(name) - 1); printf("Server:\t%s\n", name); printf("Total Users:\t%d\n", info2->num_domain_usrs); printf("Total Groups:\t%d\n", info2->num_domain_grps); printf("Total Aliases:\t%d\n", info2->num_local_grps); printf("Sequence No:\t%d\n", info2->seq_num); printf("Unknown 0:\t0x%x\n", info2->unknown_0); printf("Unknown 1:\t0x%x\n", info2->unknown_1); printf("Unknown 2:\t0x%x\n", info2->unknown_2); printf("Unknown 3:\t0x%x\n", info2->unknown_3); printf("Unknown 4:\t0x%x\n", info2->unknown_4); printf("Unknown 5:\t0x%x\n", info2->unknown_5); printf("Unknown 6:\t0x%x\n", info2->unknown_6); }
WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u, NETDFS_R_DFS_GETINFO *r_u) { UNISTR2* uni_path = &q_u->path; uint32 level = q_u->level; int consumedcnt = sizeof(pstring); pstring path; BOOL ret = False; BOOL self_ref = False; struct junction_map jn; unistr2_to_ascii(path, uni_path, sizeof(path)-1); if(!create_junction(path, &jn)) return WERR_DFS_NO_SUCH_SERVER; /* The following call can change the cwd. */ if(!NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, path, &jn, &consumedcnt, &self_ref)) || consumedcnt < strlen(path)) { vfs_ChDir(p->conn,p->conn->connectpath); return WERR_DFS_NO_SUCH_VOL; } vfs_ChDir(p->conn,p->conn->connectpath); r_u->info.switch_value = level; r_u->info.ptr0 = 1; r_u->status = WERR_OK; switch (level) { case 1: ret = init_reply_dfs_info_1(&jn, &r_u->info.u.info1); break; case 2: ret = init_reply_dfs_info_2(&jn, &r_u->info.u.info2); break; case 3: ret = init_reply_dfs_info_3(p->mem_ctx, &jn, &r_u->info.u.info3); break; case 100: ret = init_reply_dfs_info_100(&jn, &r_u->info.u.info100); break; default: r_u->info.ptr0 = 1; r_u->info.switch_value = 0; r_u->status = WERR_OK; ret = True; break; } if (!ret) r_u->status = WERR_INVALID_PARAM; return r_u->status; }
/* Query display info for a domain. This returns enough information plus a bit extra to give an overview of domain users for the User Manager application. */ static NTSTATUS query_user_list(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, uint32 *num_entries, WINBIND_USERINFO **info) { CLI_POLICY_HND *hnd; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND dom_pol; BOOL got_dom_pol = False; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; unsigned int i, start_idx, retry; uint32 loop_count; DEBUG(3,("rpc: query_user_list\n")); *num_entries = 0; *info = NULL; retry = 0; do { /* Get sam handle */ if ( !NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd)) ) return result; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; i = start_idx = 0; loop_count = 0; do { TALLOC_CTX *ctx2; uint32 num_dom_users, j; uint32 max_entries, max_size; SAM_DISPINFO_CTR ctr; SAM_DISPINFO_1 info1; ZERO_STRUCT( ctr ); ZERO_STRUCT( info1 ); ctr.sam.info1 = &info1; if (!(ctx2 = talloc_init("winbindd enum_users"))) { result = NT_STATUS_NO_MEMORY; goto done; } /* this next bit is copied from net_user_list_internal() */ get_query_dispinfo_params( loop_count, &max_entries, &max_size ); result = cli_samr_query_dispinfo(hnd->cli, mem_ctx, &dom_pol, &start_idx, 1, &num_dom_users, max_entries, max_size, &ctr); loop_count++; *num_entries += num_dom_users; *info = talloc_realloc( mem_ctx, *info, (*num_entries) * sizeof(WINBIND_USERINFO)); if (!(*info)) { result = NT_STATUS_NO_MEMORY; talloc_destroy(ctx2); goto done; } for (j = 0; j < num_dom_users; i++, j++) { fstring username, fullname; uint32 rid = ctr.sam.info1->sam[j].rid_user; unistr2_to_ascii( username, &(&ctr.sam.info1->str[j])->uni_acct_name, sizeof(username)-1); unistr2_to_ascii( fullname, &(&ctr.sam.info1->str[j])->uni_full_name, sizeof(fullname)-1); (*info)[i].acct_name = talloc_strdup(mem_ctx, username ); (*info)[i].full_name = talloc_strdup(mem_ctx, fullname ); (*info)[i].user_sid = rid_to_talloced_sid(domain, mem_ctx, rid ); /* For the moment we set the primary group for every user to be the Domain Users group. There are serious problems with determining the actual primary group for large domains. This should really be made into a 'winbind force group' smb.conf parameter or something like that. */ (*info)[i].group_sid = rid_to_talloced_sid(domain, mem_ctx, DOMAIN_GROUP_RID_USERS); } talloc_destroy(ctx2); } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); done: if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }
WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u) { struct current_user user; struct junction_map jn; struct referral* old_referral_list = NULL; BOOL self_ref = False; int consumedcnt = 0; BOOL exists = False; pstring dfspath, servername, sharename; pstring altpath; get_current_user(&user,p); if (user.ut.uid != 0) { DEBUG(10,("_dfs_add: uid != 0. Access denied.\n")); return WERR_ACCESS_DENIED; } unistr2_to_ascii(dfspath, &q_u->path, sizeof(dfspath)-1); unistr2_to_ascii(servername, &q_u->server, sizeof(servername)-1); unistr2_to_ascii(sharename, &q_u->share, sizeof(sharename)-1); DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n", dfspath, servername, sharename)); pstrcpy(altpath, servername); pstrcat(altpath, "\\"); pstrcat(altpath, sharename); /* The following call can change the cwd. */ if(NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, dfspath, &jn, &consumedcnt, &self_ref))) { exists = True; jn.referral_count += 1; old_referral_list = jn.referral_list; } else { jn.referral_count = 1; } vfs_ChDir(p->conn,p->conn->connectpath); jn.referral_list = TALLOC_ARRAY(p->mem_ctx, struct referral, jn.referral_count); if(jn.referral_list == NULL) { DEBUG(0,("init_reply_dfs_add: talloc failed for referral list!\n")); return WERR_DFS_INTERNAL_ERROR; } if(old_referral_list) { memcpy(jn.referral_list, old_referral_list, sizeof(struct referral)*jn.referral_count-1); } jn.referral_list[jn.referral_count-1].proximity = 0; jn.referral_list[jn.referral_count-1].ttl = REFERRAL_TTL; pstrcpy(jn.referral_list[jn.referral_count-1].alternate_path, altpath); if(!create_msdfs_link(&jn, exists)) { vfs_ChDir(p->conn,p->conn->connectpath); return WERR_DFS_CANT_CREATE_JUNCT; } vfs_ChDir(p->conn,p->conn->connectpath); return WERR_OK; }
WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u, NETDFS_R_DFS_REMOVE *r_u) { struct current_user user; struct junction_map jn; BOOL self_ref = False; int consumedcnt = 0; BOOL found = False; pstring dfspath, servername, sharename; pstring altpath; get_current_user(&user,p); if (user.ut.uid != 0) { DEBUG(10,("_dfs_remove: uid != 0. Access denied.\n")); return WERR_ACCESS_DENIED; } unistr2_to_ascii(dfspath, &q_u->path, sizeof(dfspath)-1); if(q_u->ptr0_server) { unistr2_to_ascii(servername, &q_u->server, sizeof(servername)-1); } if(q_u->ptr0_share) { unistr2_to_ascii(sharename, &q_u->share, sizeof(sharename)-1); } if(q_u->ptr0_server && q_u->ptr0_share) { pstrcpy(altpath, servername); pstrcat(altpath, "\\"); pstrcat(altpath, sharename); strlower_m(altpath); } DEBUG(5,("init_reply_dfs_remove: Request to remove %s -> %s\\%s.\n", dfspath, servername, sharename)); if(!NT_STATUS_IS_OK(get_referred_path(p->mem_ctx, dfspath, &jn, &consumedcnt, &self_ref))) { return WERR_DFS_NO_SUCH_VOL; } /* if no server-share pair given, remove the msdfs link completely */ if(!q_u->ptr0_server && !q_u->ptr0_share) { if(!remove_msdfs_link(&jn)) { vfs_ChDir(p->conn,p->conn->connectpath); return WERR_DFS_NO_SUCH_VOL; } vfs_ChDir(p->conn,p->conn->connectpath); } else { int i=0; /* compare each referral in the list with the one to remove */ DEBUG(10,("altpath: .%s. refcnt: %d\n", altpath, jn.referral_count)); for(i=0;i<jn.referral_count;i++) { pstring refpath; pstrcpy(refpath,jn.referral_list[i].alternate_path); trim_char(refpath, '\\', '\\'); DEBUG(10,("_dfs_remove: refpath: .%s.\n", refpath)); if(strequal(refpath, altpath)) { *(jn.referral_list[i].alternate_path)='\0'; DEBUG(10,("_dfs_remove: Removal request matches referral %s\n", refpath)); found = True; } } if(!found) { return WERR_DFS_NO_SUCH_SHARE; } /* Only one referral, remove it */ if(jn.referral_count == 1) { if(!remove_msdfs_link(&jn)) { vfs_ChDir(p->conn,p->conn->connectpath); return WERR_DFS_NO_SUCH_VOL; } } else { if(!create_msdfs_link(&jn, True)) { vfs_ChDir(p->conn,p->conn->connectpath); return WERR_DFS_CANT_CREATE_JUNCT; } } vfs_ChDir(p->conn,p->conn->connectpath); } return WERR_OK; }
static int reply_spnego_kerberos(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, DATA_BLOB *secblob, BOOL *p_invalidate_vuid) { TALLOC_CTX *mem_ctx; DATA_BLOB ticket; char *client, *p, *domain; fstring netbios_domain_name; struct passwd *pw; fstring user; int sess_vuid; NTSTATUS ret; PAC_DATA *pac_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob(NULL, 0); uint8 tok_id[2]; DATA_BLOB nullblob = data_blob(NULL, 0); fstring real_username; BOOL map_domainuser_to_guest = False; BOOL username_was_mapped; PAC_LOGON_INFO *logon_info = NULL; ZERO_STRUCT(ticket); ZERO_STRUCT(pac_data); ZERO_STRUCT(ap_rep); ZERO_STRUCT(ap_rep_wrapped); ZERO_STRUCT(response); /* Normally we will always invalidate the intermediate vuid. */ *p_invalidate_vuid = True; mem_ctx = talloc_init("reply_spnego_kerberos"); if (mem_ctx == NULL) { return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY)); } if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { talloc_destroy(mem_ctx); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key); data_blob_free(&ticket); if (!NT_STATUS_IS_OK(ret)) { #if 0 /* Experiment that failed. See "only happens with a KDC" comment below. */ if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { /* * Windows in this case returns NT_STATUS_MORE_PROCESSING_REQUIRED * with a negTokenTarg blob containing an krb5_error struct ASN1 encoded * containing KRB5KRB_AP_ERR_SKEW. The client then fixes its * clock and continues rather than giving an error. JRA. * -- Looks like this only happens with a KDC. JRA. */ BOOL ok = make_krb5_skew_error(&ap_rep); if (!ok) { talloc_destroy(mem_ctx); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR); response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED); /* * In this one case we don't invalidate the intermediate vuid. * as we're expecting the client to re-use it for the next * sessionsetupX packet. JRA. */ *p_invalidate_vuid = False; data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&response); talloc_destroy(mem_ctx); return -1; /* already replied */ } #else if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { ret = NT_STATUS_LOGON_FAILURE; } #endif DEBUG(1,("Failed to verify incoming ticket with error %s!\n", nt_errstr(ret))); talloc_destroy(mem_ctx); return ERROR_NT(nt_status_squash(ret)); } DEBUG(3,("Ticket name is [%s]\n", client)); p = strchr_m(client, '@'); if (!p) { DEBUG(3,("Doesn't look like a valid principal\n")); data_blob_free(&ap_rep); data_blob_free(&session_key); SAFE_FREE(client); talloc_destroy(mem_ctx); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } *p = 0; /* save the PAC data if we have it */ if (pac_data) { logon_info = get_logon_info_from_pac(pac_data); if (logon_info) { netsamlogon_cache_store( client, &logon_info->info3 ); } } if (!strequal(p+1, lp_realm())) { DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1)); if (!lp_allow_trusted_domains()) { data_blob_free(&ap_rep); data_blob_free(&session_key); SAFE_FREE(client); talloc_destroy(mem_ctx); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } } /* this gives a fully qualified user name (ie. with full realm). that leads to very long usernames, but what else can we do? */ domain = p+1; if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1); domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); } else { /* If we have winbind running, we can (and must) shorten the username by using the short netbios name. Otherwise we will have inconsistent user names. With Kerberos, we get the fully qualified realm, with ntlmssp we get the short name. And even w2k3 does use ntlmssp if you for example connect to an ip address. */ struct winbindd_request wb_request; struct winbindd_response wb_response; NSS_STATUS wb_result; ZERO_STRUCT(wb_request); ZERO_STRUCT(wb_response); DEBUG(10, ("Mapping [%s] to short name\n", domain)); fstrcpy(wb_request.domain_name, domain); wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO, &wb_request, &wb_response); if (wb_result == NSS_STATUS_SUCCESS) { fstrcpy(netbios_domain_name, wb_response.data.domain_info.name); domain = netbios_domain_name; DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain)); } else { DEBUG(3, ("Could not find short name -- winbind " "not running?\n")); } } fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client); /* lookup the passwd struct, create a new user if necessary */ username_was_mapped = map_username( user ); pw = smb_getpwnam( mem_ctx, user, real_username, True ); if (pw) { /* if a real user check pam account restrictions */ /* only really perfomed if "obey pam restriction" is true */ /* do this before an eventual mappign to guest occurs */ ret = smb_pam_accountcheck(pw->pw_name); if ( !NT_STATUS_IS_OK(ret)) { DEBUG(1, ("PAM account restriction prevents user login\n")); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); return ERROR_NT(nt_status_squash(ret)); } } if (!pw) { /* this was originally the behavior of Samba 2.2, if a user did not have a local uid but has been authenticated, then map them to a guest account */ if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ map_domainuser_to_guest = True; fstrcpy(user,lp_guestaccount()); pw = smb_getpwnam( mem_ctx, user, real_username, True ); } /* extra sanity check that the guest account is valid */ if ( !pw ) { DEBUG(1,("Username %s is invalid on this system\n", user)); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } } /* setup the string used by %U */ sub_set_smb_name( real_username ); reload_services(True); if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); } else if (logon_info) { /* pass the unmapped username here since map_username() will be called again from inside make_server_info_info3() */ ret = make_server_info_info3(mem_ctx, client, domain, &server_info, &logon_info->info3); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_info3 failed: %s!\n", nt_errstr(ret))); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); return ERROR_NT(nt_status_squash(ret)); } } else { ret = make_server_info_pw(&server_info, real_username, pw); if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_pw failed: %s!\n", nt_errstr(ret))); SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE(mem_ctx); return ERROR_NT(nt_status_squash(ret)); } /* make_server_info_pw does not set the domain. Without this * we end up with the local netbios name in substitutions for * %D. */ if (server_info->sam_account != NULL) { pdb_set_domain(server_info->sam_account, domain, PDB_SET); } } server_info->was_mapped |= username_was_mapped; /* we need to build the token for the user. make_server_info_guest() already does this */ if ( !server_info->ptok ) { ret = create_local_token( server_info ); if ( !NT_STATUS_IS_OK(ret) ) { SAFE_FREE(client); data_blob_free(&ap_rep); data_blob_free(&session_key); TALLOC_FREE( mem_ctx ); TALLOC_FREE( server_info ); return ERROR_NT(nt_status_squash(ret)); } } /* register_vuid keeps the server info */ /* register_vuid takes ownership of session_key, no need to free after this. A better interface would copy it.... */ sess_vuid = register_vuid(server_info, session_key, nullblob, client); SAFE_FREE(client); if (sess_vuid == UID_FIELD_INVALID ) { ret = NT_STATUS_LOGON_FAILURE; } else { /* current_user_info is changed on new vuid */ reload_services( True ); set_message(outbuf,4,0,True); SSVAL(outbuf, smb_vwv3, 0); if (server_info->guest) { SSVAL(outbuf,smb_vwv2,1); } SSVAL(outbuf, smb_uid, sess_vuid); sessionsetup_start_signing_engine(server_info, inbuf); } /* wrap that up in a nice GSS-API wrapping */ if (NT_STATUS_IS_OK(ret)) { ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP); } else { ap_rep_wrapped = data_blob(NULL, 0); } response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD); reply_sesssetup_blob(conn, outbuf, response, ret); data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&response); TALLOC_FREE(mem_ctx); return -1; /* already replied */ }
/**************************************************************************** display sam_user_info_21 structure ****************************************************************************/ static void display_sam_user_info_21(SAM_USER_INFO_21 *usr) { fstring temp; unistr2_to_ascii(temp, &usr->uni_user_name, sizeof(temp)-1); printf("\tUser Name :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_full_name, sizeof(temp)-1); printf("\tFull Name :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_home_dir, sizeof(temp)-1); printf("\tHome Drive :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_dir_drive, sizeof(temp)-1); printf("\tDir Drive :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_profile_path, sizeof(temp)-1); printf("\tProfile Path:\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_logon_script, sizeof(temp)-1); printf("\tLogon Script:\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_acct_desc, sizeof(temp)-1); printf("\tDescription :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_workstations, sizeof(temp)-1); printf("\tWorkstations:\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_unknown_str, sizeof(temp)-1); printf("\tUnknown Str :\t%s\n", temp); unistr2_to_ascii(temp, &usr->uni_munged_dial, sizeof(temp)-1); printf("\tRemote Dial :\t%s\n", temp); printf("\tLogon Time :\t%s\n", http_timestring(nt_time_to_unix(&usr->logon_time))); printf("\tLogoff Time :\t%s\n", http_timestring(nt_time_to_unix(&usr->logoff_time))); printf("\tKickoff Time :\t%s\n", http_timestring(nt_time_to_unix(&usr->kickoff_time))); printf("\tPassword last set Time :\t%s\n", http_timestring(nt_time_to_unix(&usr->pass_last_set_time))); printf("\tPassword can change Time :\t%s\n", http_timestring(nt_time_to_unix(&usr->pass_can_change_time))); printf("\tPassword must change Time:\t%s\n", http_timestring(nt_time_to_unix(&usr->pass_must_change_time))); printf("\tunknown_2[0..31]...\n"); /* user passwords? */ printf("\tuser_rid :\t0x%x\n" , usr->user_rid ); /* User ID */ printf("\tgroup_rid:\t0x%x\n" , usr->group_rid); /* Group ID */ printf("\tacb_info :\t0x%04x\n", usr->acb_info ); /* Account Control Info */ printf("\tunknown_3:\t0x%08x\n", usr->unknown_3); /* 0x00ff ffff */ printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */ printf("\tbad_password_count:\t0x%08x\n", usr->bad_password_count); printf("\tlogon_count:\t0x%08x\n", usr->logon_count); printf("\tpadding1[0..7]...\n"); if (usr->ptr_logon_hrs) { printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len); } }
static void display_sam_sync(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas, SAM_DELTA_CTR *deltas) { fstring name; uint32 i, j; for (i = 0; i < num_deltas; i++) { switch (hdr_deltas[i].type) { case SAM_DELTA_DOMAIN_INFO: unistr2_to_ascii(name, &deltas[i].domain_info.uni_dom_name, sizeof(name) - 1); printf("Domain: %s\n", name); break; case SAM_DELTA_GROUP_INFO: unistr2_to_ascii(name, &deltas[i].group_info.uni_grp_name, sizeof(name) - 1); printf("Group: %s\n", name); break; case SAM_DELTA_ACCOUNT_INFO: unistr2_to_ascii(name, &deltas[i].account_info.uni_acct_name, sizeof(name) - 1); printf("Account: %s\n", name); break; case SAM_DELTA_ALIAS_INFO: unistr2_to_ascii(name, &deltas[i].alias_info.uni_als_name, sizeof(name) - 1); printf("Alias: %s\n", name); break; case SAM_DELTA_ALIAS_MEM: { SAM_ALIAS_MEM_INFO *alias = &deltas[i].als_mem_info; for (j = 0; j < alias->num_members; j++) { fstring sid_str; sid_to_string(sid_str, &alias->sids[j].sid); printf("%s\n", sid_str); } break; } case SAM_DELTA_GROUP_MEM: { SAM_GROUP_MEM_INFO *group = &deltas[i].grp_mem_info; for (j = 0; j < group->num_members; j++) printf("rid 0x%x, attrib 0x%08x\n", group->rids[j], group->attribs[j]); break; } case SAM_DELTA_MODIFIED_COUNT: { SAM_DELTA_MOD_COUNT *mc = &deltas[i].mod_count; printf("sam sequence update: 0x%04x\n", mc->seqnum); break; } default: printf("unknown delta type 0x%02x\n", hdr_deltas[i].type); break; } } }
const char *unistr2_static(const UNISTR2 *str) { static pstring ret; unistr2_to_ascii(ret, str, sizeof(ret)); return ret; }
NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u) { uint32 flags = 0x0; uint32 pdc_connection_status = 0x0; uint32 logon_attempts = 0x0; uint32 tc_status; fstring servername, domain, dc_name, dc_name2; struct in_addr dc_ip; /* this should be \\global_myname() */ unistr2_to_ascii(servername, &q_u->uni_server_name, sizeof(servername)); r_u->status = NT_STATUS_OK; tc_status = ERROR_NO_SUCH_DOMAIN; fstrcpy( dc_name, "" ); switch ( q_u->function_code ) { case NETLOGON_CONTROL_TC_QUERY: unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain)); if ( !is_trusted_domain( domain ) ) break; if ( !get_dc_name( domain, NULL, dc_name2, &dc_ip ) ) { tc_status = ERROR_NO_LOGON_SERVERS; break; } fstr_sprintf( dc_name, "\\\\%s", dc_name2 ); tc_status = NO_ERROR; break; case NETLOGON_CONTROL_REDISCOVER: unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain)); if ( !is_trusted_domain( domain ) ) break; if ( !get_dc_name( domain, NULL, dc_name2, &dc_ip ) ) { tc_status = ERROR_NO_LOGON_SERVERS; break; } fstr_sprintf( dc_name, "\\\\%s", dc_name2 ); tc_status = NO_ERROR; break; default: /* no idea what this should be */ DEBUG(0,("_net_logon_ctrl2: unimplemented function level [%d]\n", q_u->function_code)); } /* prepare the response */ init_net_r_logon_ctrl2( r_u, q_u->query_level, flags, pdc_connection_status, logon_attempts, tc_status, dc_name ); if (lp_server_role() == ROLE_DOMAIN_BDC) send_sync_message(); return r_u->status; }