void conn_free(connection_struct *conn) { /* Free vfs_connection_struct */ if (conn->dl_handle != NULL) { /* Close dlopen() handle */ sys_dlclose(conn->dl_handle); } DLIST_REMOVE(Connections, conn); if (conn->ngroups && conn->groups) { SAFE_FREE(conn->groups); conn->groups = NULL; conn->ngroups = 0; } delete_nt_token(&conn->nt_user_token); free_namearray(conn->veto_list); free_namearray(conn->hide_list); free_namearray(conn->veto_oplock_list); string_free(&conn->user); string_free(&conn->dirpath); string_free(&conn->connectpath); string_free(&conn->origpath); bitmap_clear(bmap, conn->cnum); num_open--; ZERO_STRUCTP(conn); SAFE_FREE(conn); }
void invalidate_vuid(uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); if (vuser == NULL) return; SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); SAFE_FREE(vuser->logon_script); session_yield(vuser); SAFE_FREE(vuser->session_keystr); free_server_info(&vuser->server_info); data_blob_free(&vuser->session_key); DLIST_REMOVE(validated_users, vuser); /* clear the vuid from the 'cache' on each connection, and from the vuid 'owner' of connections */ conn_clear_vuid_cache(vuid); SAFE_FREE(vuser->groups); delete_nt_token(&vuser->nt_user_token); SAFE_FREE(vuser); num_validated_vuids--; }
BOOL pop_sec_ctx(void) { struct sec_ctx *ctx_p; struct sec_ctx *prev_ctx_p; /* Check for stack underflow */ if (sec_ctx_stack_ndx == 0) { DEBUG(0, ("Security context stack underflow!\n")); smb_panic("Security context stack underflow!\n"); } ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; /* Clear previous user info */ ctx_p->uid = (uid_t)-1; ctx_p->gid = (gid_t)-1; SAFE_FREE(ctx_p->groups); ctx_p->ngroups = 0; delete_nt_token(&ctx_p->token); /* Pop back previous user */ sec_ctx_stack_ndx--; gain_root(); prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; #ifdef HAVE_SETGROUPS sys_setgroups(prev_ctx_p->ngroups, prev_ctx_p->groups); #endif become_id(prev_ctx_p->uid, prev_ctx_p->gid); /* Update current_user stuff */ current_user.uid = prev_ctx_p->uid; current_user.gid = prev_ctx_p->gid; current_user.ngroups = prev_ctx_p->ngroups; current_user.groups = prev_ctx_p->groups; current_user.nt_user_token = prev_ctx_p->token; DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", (unsigned int)geteuid(), (unsigned int)getegid(), sec_ctx_stack_ndx)); return True; }
void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; /* Set the security context */ DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx)); if (ngroups) { int i; DEBUG(3, ("%d user groups: \n", ngroups)); for (i = 0; i < ngroups; i++) { DEBUGADD(3, ("%u ", (unsigned int)groups[i])); } DEBUG(3, ("\n")); } gain_root(); #ifdef HAVE_SETGROUPS sys_setgroups(ngroups, groups); #endif ctx_p->ngroups = ngroups; SAFE_FREE(ctx_p->groups); if (token && (token == ctx_p->token)) smb_panic("DUPLICATE_TOKEN"); delete_nt_token(&ctx_p->token); ctx_p->groups = memdup(groups, sizeof(gid_t) * ngroups); ctx_p->token = dup_nt_token(token); become_id(uid, gid); ctx_p->uid = uid; ctx_p->gid = gid; /* Update current_user stuff */ current_user.uid = uid; current_user.gid = gid; current_user.ngroups = ngroups; current_user.groups = groups; current_user.nt_user_token = ctx_p->token; }
BOOL push_sec_ctx(void) { struct sec_ctx *ctx_p; /* Check we don't overflow our stack */ if (sec_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) { DEBUG(0, ("Security context stack overflow!\n")); smb_panic("Security context stack overflow!\n"); } /* Store previous user context */ sec_ctx_stack_ndx++; ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; ctx_p->uid = geteuid(); ctx_p->gid = getegid(); DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n", (unsigned int)ctx_p->uid, (unsigned int)ctx_p->gid, sec_ctx_stack_ndx )); ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token); ctx_p->ngroups = sys_getgroups(0, NULL); if (ctx_p->ngroups != 0) { if (!(ctx_p->groups = malloc(ctx_p->ngroups * sizeof(gid_t)))) { DEBUG(0, ("Out of memory in push_sec_ctx()\n")); delete_nt_token(&ctx_p->token); return False; } sys_getgroups(ctx_p->ngroups, ctx_p->groups); } else { ctx_p->groups = NULL; } return True; }
BOOL change_to_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; gid_t gid; uid_t uid; char group_c; BOOL must_free_token = False; NT_USER_TOKEN *token = NULL; if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); return(False); } /* * We need a separate check in security=share mode due to vuid * always being UID_FIELD_INVALID. If we don't do this then * in share mode security we are *always* changing uid's between * SMB's - this hurts performance - Badly. */ if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && (current_user.uid == conn->uid)) { DEBUG(4,("change_to_user: Skipping user change - already user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && (current_user.uid == vuser->uid)) { DEBUG(4,("change_to_user: Skipping user change - already user\n")); return True; } snum = SNUM(conn); if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) return False; if (conn->force_user || conn->admin_user || (lp_security() == SEC_SHARE)) { uid = conn->uid; gid = conn->gid; current_user.groups = conn->groups; current_user.ngroups = conn->ngroups; token = conn->nt_user_token; } else { if (!vuser) { DEBUG(2,("change_to_user: Invalid vuid used %d\n",vuid)); return(False); } uid = vuser->uid; gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; token = vuser->nt_user_token; } /* * See if we should force group for this service. * If so this overrides any group set in the force * user code. */ if((group_c = *lp_force_group(snum))) { BOOL is_guest = False; if(group_c == '+') { /* * Only force group if the user is a member of * the service group. Check the group memberships for * this user (we already have this) to * see if we should force the group. */ int i; for (i = 0; i < current_user.ngroups; i++) { if (current_user.groups[i] == conn->gid) { gid = conn->gid; break; } } } else { gid = conn->gid; } /* * We've changed the group list in the token - we must * re-create it. */ if (vuser && vuser->guest) is_guest = True; token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest, NULL); must_free_token = True; } set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token); /* * Free the new token (as set_sec_ctx copies it). */ if (must_free_token) delete_nt_token(&token); current_user.conn = conn; current_user.vuid = vuid; DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); return(True); }
void add_supplementary_nt_login_groups(int *n_groups, gid_t **pp_groups, NT_USER_TOKEN **pptok) { int total_groups; int current_n_groups = *n_groups; gid_t *final_groups = NULL; size_t i; NT_USER_TOKEN *ptok = *pptok; NT_USER_TOKEN *new_tok = NULL; if (!ptok || (ptok->num_sids == 0)) return; new_tok = dup_nt_token(ptok); if (!new_tok) { DEBUG(0,("add_supplementary_nt_login_groups: Failed to malloc new token\n")); return; } /* Leave the allocated space but empty the number of SIDs. */ new_tok->num_sids = 0; total_groups = current_n_groups + ptok->num_sids; final_groups = (gid_t *)malloc(total_groups * sizeof(gid_t)); if (!final_groups) { DEBUG(0,("add_supplementary_nt_login_groups: Failed to malloc new groups.\n")); delete_nt_token(&new_tok); return; } memcpy(final_groups, *pp_groups, current_n_groups * sizeof(gid_t)); for (i = 0; i < ptok->num_sids; i++) { enum SID_NAME_USE sid_type; gid_t new_grp; if (sid_to_gid(&ptok->user_sids[i], &new_grp, &sid_type)) { /* * Don't add the gid_t if it is already in the current group * list. Some UNIXen don't like the same group more than once. */ int j; for (j = 0; j < current_n_groups; j++) if (final_groups[j] == new_grp) break; if ( j == current_n_groups) { /* Group not already present. */ final_groups[current_n_groups++] = new_grp; } } else { /* SID didn't map. Copy to the new token to be saved. */ sid_copy(&new_tok->user_sids[new_tok->num_sids++], &ptok->user_sids[i]); } } SAFE_FREE(*pp_groups); *pp_groups = final_groups; *n_groups = current_n_groups; /* Replace the old token with the truncated one. */ delete_nt_token(&ptok); *pptok = new_tok; }
static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlmssp_resp) { uchar lm_owf[24]; uchar nt_owf[128]; int nt_pw_len; int lm_pw_len; fstring user_name; fstring domain; fstring wks; NTSTATUS nt_status; struct auth_context *auth_context = NULL; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); memset(p->user_name, '\0', sizeof(p->user_name)); memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name)); memset(p->domain, '\0', sizeof(p->domain)); memset(p->wks, '\0', sizeof(p->wks)); /* Set up for non-authenticated user. */ delete_nt_token(&p->pipe_user.nt_user_token); p->pipe_user.ngroups = 0; SAFE_FREE( p->pipe_user.groups); /* * Setup an empty password for a guest user. */ /* * We always negotiate UNICODE. */ if (p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_UNICODE) { rpcstr_pull(user_name, ntlmssp_resp->user, sizeof(fstring), ntlmssp_resp->hdr_usr.str_str_len*2, 0 ); rpcstr_pull(domain, ntlmssp_resp->domain, sizeof(fstring), ntlmssp_resp->hdr_domain.str_str_len*2, 0); rpcstr_pull(wks, ntlmssp_resp->wks, sizeof(fstring), ntlmssp_resp->hdr_wks.str_str_len*2, 0); } else { pull_ascii_fstring(user_name, ntlmssp_resp->user); pull_ascii_fstring(domain, ntlmssp_resp->domain); pull_ascii_fstring(wks, ntlmssp_resp->wks); } DEBUG(5,("user: %s domain: %s wks: %s\n", user_name, domain, wks)); nt_pw_len = MIN(sizeof(nt_owf), ntlmssp_resp->hdr_nt_resp.str_str_len); lm_pw_len = MIN(sizeof(lm_owf), ntlmssp_resp->hdr_lm_resp.str_str_len); memcpy(lm_owf, ntlmssp_resp->lm_resp, sizeof(lm_owf)); memcpy(nt_owf, ntlmssp_resp->nt_resp, nt_pw_len); #ifdef DEBUG_PASSWORD DEBUG(100,("lm, nt owfs, chal\n")); dump_data(100, (char *)lm_owf, sizeof(lm_owf)); dump_data(100, (char *)nt_owf, nt_pw_len); dump_data(100, (char *)p->challenge, 8); #endif /* * Allow guest access. Patch from Shirish Kalele <*****@*****.**>. */ if (*user_name) { /* * Do the length checking only if user is not NULL. */ if (ntlmssp_resp->hdr_lm_resp.str_str_len == 0) return False; if (ntlmssp_resp->hdr_nt_resp.str_str_len == 0) return False; if (ntlmssp_resp->hdr_usr.str_str_len == 0) return False; if (ntlmssp_resp->hdr_domain.str_str_len == 0) return False; if (ntlmssp_resp->hdr_wks.str_str_len == 0) return False; } make_auth_context_fixed(&auth_context, (uchar*)p->challenge); if (!make_user_info_netlogon_network(&user_info, user_name, domain, wks, lm_owf, lm_pw_len, nt_owf, nt_pw_len)) { DEBUG(0,("make_user_info_netlogon_network failed! Failing authenticaion.\n")); return False; } nt_status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); (auth_context->free)(&auth_context); free_user_info(&user_info); p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status); if (!p->ntlmssp_auth_validated) { DEBUG(1,("api_pipe_ntlmssp_verify: User [%s]\\[%s] from machine %s \ failed authentication on named pipe %s.\n", domain, user_name, wks, p->name )); free_server_info(&server_info); return False; }