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--; }
/* * * free_server - free a server and possibly its queues also * * sinfo - the server_info list head * free_queues_too - flag to free the queues attached to server also * * returns nothing * */ void free_server(server_info *sinfo, int free_objs_too) { if (sinfo == NULL) return; if (free_objs_too) { free_queues(sinfo -> queues, 1); free_nodes(sinfo -> nodes); } free_token_list(sinfo -> tokens); free_server_info(sinfo); }
void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state) { TALLOC_CTX *mem_ctx = (*auth_ntlmssp_state)->mem_ctx; if ((*auth_ntlmssp_state)->ntlmssp_state) { ntlmssp_end(&(*auth_ntlmssp_state)->ntlmssp_state); } if ((*auth_ntlmssp_state)->auth_context) { ((*auth_ntlmssp_state)->auth_context->free)(&(*auth_ntlmssp_state)->auth_context); } if ((*auth_ntlmssp_state)->server_info) { free_server_info(&(*auth_ntlmssp_state)->server_info); } talloc_destroy(mem_ctx); *auth_ntlmssp_state = NULL; }
/** * COMMAND /disconnect * * Terminate connection or abort a connection process. */ static int cmd_disconnect(int argc, dstring** argv) { mutex_lock(&client.network_lock); if (client.state == SVCECLIENT_STATE_CONNECTED) { free_server_info(); enet_peer_disconnect(client.client, 0); enet_host_destroy(client.host); client.client = NULL; client.host = NULL; client.state = SVCECLIENT_STATE_DISCONNECTED; msg_state(); } else if (client.state == SVCECLIENT_STATE_CONNECTING) { enet_peer_disconnect(client.client, 0); enet_host_destroy(client.host); client.client = NULL; client.host = NULL; client.state = SVCECLIENT_STATE_DISCONNECTED; msg_state(); } else { fprintf(stderr, "Not connected.\n"); } mutex_unlock(&client.network_lock); return 0; }
// Sends an intialize message to the server // @param sockfd the socket file descriptor // @param server the server being sent to // @param seq the sequence number of the message // @param file a pointer to the file variable // @param client a pointer to the client variable // @param hftpd a pointer to the server information // @param p a pointer to the filename // @param count the position in the list of files static void send_initialize(int sockfd, host *server, int *seq, file_info *file, client_info *client, server_info *hftpd, csv_record *p, int count) { hftp_control_message *control = (hftp_control_message*)create_control_message(INITIALIZE, *seq, p, client->token, file->file_length); syslog(LOG_INFO, "Transferring '%s' (%d of %d)", p->filename, count, get_list_length(client->response_list)); syslog(LOG_DEBUG, "Type: Initialization, Sequence: %d, Filename length: %d", control->sequence, ntohs(control->filename_length)); // Transmit a control request if (transmit(sockfd, (message**)&control, server, seq) == -1) { syslog(LOG_INFO, "Authentication with Hooli file transfer server failed"); free_file_info(file); close(sockfd); free_server_info(hftpd); free_client_info(client); exit(EXIT_FAILURE); } //end if } //end send_control
/** * Free client state. */ void quit_client_state() { int input_error; /* free enet structures */ if (client.client) enet_peer_disconnect(client.client, 0); if (client.host) enet_host_destroy(client.host); /* get thread status */ mutex_lock(&client.input_lock); input_error = client.input_error; mutex_unlock(&client.input_lock); /* cancel the input thread if needed */ if (!input_error) { mutex_lock(&client.input_lock); thread_cancel(client.input_thread); mutex_unlock(&client.input_lock); } /* join a canceled thread */ thread_join(client.input_thread); /* destroy the input lock */ mutex_destroy(&client.input_lock); mutex_destroy(&client.network_lock); /* free other input resources */ free(client.input_buffer); dlist_free(client.input_queue); dfree(client.server_host_addr); dfree(client.server_host_name); free_server_info(); }
int main(int argc, char* argv[]) { dstring* input; int input_done; int code; ENetEvent event; if (argc > 1) { fprintf(stderr, "svcc doesn't accept any command line arguments, use stdin instead.\n"); return 1; } /* initialize enet */ if (enet_initialize()) { fprintf(stderr, "Failed to initialize ENet\n"); return 1; } /* initialize client state */ init_client_state(); /* init SVC */ svc_init(send_callback); /* main loop */ input = dnew(); client.main_done = 0; signal(SIGINT, sigint); while(!client.main_done) { /* enet event handler */ if (client.state == SVCECLIENT_STATE_CONNECTED) { /* handle connection state */ while (1) { mutex_lock(&client.network_lock); code = enet_host_service(client.host, &event, 0); mutex_unlock(&client.network_lock); if (code <= 0) break; /* handle event */ switch(event.type) { case ENET_EVENT_TYPE_DISCONNECT: /* we got disconnected */ mutex_lock(&client.network_lock); client.state = SVCECLIENT_STATE_DISCONNECTED; free_server_info(); mutex_unlock(&client.network_lock); msg_state(); break; case ENET_EVENT_TYPE_RECEIVE: /* some data just arrived */ if (event.channelID == 0) { handle_server_msg(event.packet); } else if (event.channelID == 1) { handle_server_audio(event.packet); } else { fprintf(stderr, "Received message from server on invalid channel %i.\n", event.channelID); } mutex_lock(&client.network_lock); enet_packet_destroy(event.packet); mutex_unlock(&client.network_lock); break; case ENET_EVENT_TYPE_CONNECT: /* no one will connect, ignore the bastard */ default: break; } } } else if (client.state == SVCECLIENT_STATE_CONNECTING) { /* handle connecting state */ mutex_lock(&client.network_lock); code = enet_host_service(client.host, &event, 0); mutex_unlock(&client.network_lock); if (code > 0) { if (event.type == ENET_EVENT_TYPE_CONNECT) { client.state = SVCECLIENT_STATE_CONNECTED; client.server_info = dsdict_new(); msg_state(); } else { mutex_lock(&client.network_lock); client.state = SVCECLIENT_STATE_DISCONNECTED; enet_peer_disconnect(client.client, 0); client.client = NULL; enet_host_destroy(client.host); client.host = NULL; msg_state(); mutex_unlock(&client.network_lock); } } } else { /* sleep for 8ms */ usleep(8000); } /* play with the input queue */ if (!client.main_done) { input_done = 0; while (!input_done) { /* get next input command */ mutex_lock(&client.input_lock); if (client.input_queue->size) { dcpy(input, client.input_queue->front->string); dlist_erase(client.input_queue, client.input_queue->front); } else { input_done = 1; } mutex_unlock(&client.input_lock); /* quit input loop if queue is empty */ if (input_done) { break; } /* handle commands */ input_done = client.main_done = handle_input_command(input); } } /* check if input died for some reasons */ mutex_lock(&client.input_lock); if (client.input_error) { /* if so, leave main loop */ client.main_done = 1; } mutex_unlock(&client.input_lock); fflush(stdout); fflush(stderr); /* sleep for 8ms */ usleep(8000); } fprintf(stdout, ":STATE exiting\n"); dfree(input); svc_close(); quit_client_state(); enet_deinitialize(); return 0; }
NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u) { NTSTATUS status = NT_STATUS_OK; NET_USER_INFO_3 *usr_info = NULL; NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr; DOM_CRED srv_cred; UNISTR2 *uni_samlogon_user = NULL; UNISTR2 *uni_samlogon_domain = NULL; UNISTR2 *uni_samlogon_workstation = NULL; fstring nt_username, nt_domain, nt_workstation; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; extern userdom_struct current_user_info; SAM_ACCOUNT *sampw; struct auth_context *auth_context = NULL; usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3)); if (!usr_info) return NT_STATUS_NO_MEMORY; ZERO_STRUCTP(usr_info); /* store the user information, if there is any. */ r_u->user = usr_info; r_u->switch_value = 0; /* indicates no info */ r_u->auth_resp = 1; /* authoritative response */ r_u->switch_value = 3; /* indicates type of validation user info */ if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; if ( (lp_server_schannel() == True) && (!p->netsec_auth_validated) ) { /* 'server schannel = yes' should enforce use of schannel, the client did offer it in auth2, but obviously did not use it. */ return NT_STATUS_ACCESS_DENIED; } /* checks and updates credentials. creates reply credentials */ if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred))) return NT_STATUS_INVALID_HANDLE; memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); r_u->buffer_creds = 1; /* yes, we have valid server credentials */ memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds)); /* find the username */ switch (q_u->sam_id.logon_level) { case INTERACTIVE_LOGON_TYPE: uni_samlogon_user = &ctr->auth.id1.uni_user_name; uni_samlogon_domain = &ctr->auth.id1.uni_domain_name; uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name; DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup())); break; case NET_LOGON_TYPE: uni_samlogon_user = &ctr->auth.id2.uni_user_name; uni_samlogon_domain = &ctr->auth.id2.uni_domain_name; uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name; DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup())); break; default: DEBUG(2,("SAM Logon: unsupported switch value\n")); return NT_STATUS_INVALID_INFO_CLASS; } /* end switch */ rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0); rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0); rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0); DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, nt_workstation, nt_domain)); fstrcpy(current_user_info.smb_name, nt_username); sub_set_smb_name(nt_username); DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username)); status = NT_STATUS_OK; switch (ctr->switch_value) { case NET_LOGON_TYPE: { const char *wksname = nt_workstation; if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) { return status; } /* For a network logon, the workstation name comes in with two * backslashes in the front. Strip them if they are there. */ if (*wksname == '\\') wksname++; if (*wksname == '\\') wksname++; /* Standard challenge/response authenticaion */ if (!make_user_info_netlogon_network(&user_info, nt_username, nt_domain, wksname, ctr->auth.id2.lm_chal_resp.buffer, ctr->auth.id2.lm_chal_resp.str_str_len, ctr->auth.id2.nt_chal_resp.buffer, ctr->auth.id2.nt_chal_resp.str_str_len)) { status = NT_STATUS_NO_MEMORY; } break; } case INTERACTIVE_LOGON_TYPE: /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted with the session key. We will convert this to chellange/responce for the auth subsystem to chew on */ { const uint8 *chal; if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) { return status; } chal = auth_context->get_ntlm_challenge(auth_context); if (!make_user_info_netlogon_interactive(&user_info, nt_username, nt_domain, nt_workstation, chal, ctr->auth.id1.lm_owf.data, ctr->auth.id1.nt_owf.data, p->dc.sess_key)) { status = NT_STATUS_NO_MEMORY; } break; } default: DEBUG(2,("SAM Logon: unsupported switch value\n")); return NT_STATUS_INVALID_INFO_CLASS; } /* end switch */ if ( NT_STATUS_IS_OK(status) ) { status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); } (auth_context->free)(&auth_context); free_user_info(&user_info); DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", nt_errstr(status))); /* Check account and password */ if (!NT_STATUS_IS_OK(status)) { free_server_info(&server_info); return status; } if (server_info->guest) { /* We don't like guest domain logons... */ DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n")); free_server_info(&server_info); return NT_STATUS_LOGON_FAILURE; } /* This is the point at which, if the login was successful, that the SAM Local Security Authority should record that the user is logged in to the domain. */ { DOM_GID *gids = NULL; const DOM_SID *user_sid = NULL; const DOM_SID *group_sid = NULL; DOM_SID domain_sid; uint32 user_rid, group_rid; int num_gids = 0; pstring my_name; fstring user_sid_string; fstring group_sid_string; uchar user_session_key[16]; uchar lm_session_key[16]; uchar netlogon_sess_key[16]; sampw = server_info->sam_account; /* set up pointer indicating user/password failed to be found */ usr_info->ptr_user_info = 0; user_sid = pdb_get_user_sid(sampw); group_sid = pdb_get_group_sid(sampw); sid_copy(&domain_sid, user_sid); sid_split_rid(&domain_sid, &user_rid); if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) { DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n", pdb_get_domain(sampw), pdb_get_username(sampw), sid_to_string(user_sid_string, user_sid), sid_to_string(group_sid_string, group_sid))); return NT_STATUS_UNSUCCESSFUL; } pstrcpy(my_name, global_myname()); if (!NT_STATUS_IS_OK(status = nt_token_to_group_list(p->mem_ctx, &domain_sid, server_info->ptok, &num_gids, &gids))) { return status; } ZERO_STRUCT(netlogon_sess_key); memcpy(netlogon_sess_key, p->dc.sess_key, 8); if (server_info->user_session_key.length) { memcpy(user_session_key, server_info->user_session_key.data, MIN(sizeof(user_session_key), server_info->user_session_key.length)); SamOEMhash(user_session_key, netlogon_sess_key, 16); } if (server_info->lm_session_key.length) { memcpy(lm_session_key, server_info->lm_session_key.data, MIN(sizeof(lm_session_key), server_info->lm_session_key.length)); SamOEMhash(lm_session_key, netlogon_sess_key, 16); } ZERO_STRUCT(netlogon_sess_key); init_net_user_info3(p->mem_ctx, usr_info, user_rid, group_rid, pdb_get_username(sampw), pdb_get_fullname(sampw), pdb_get_homedir(sampw), pdb_get_dir_drive(sampw), pdb_get_logon_script(sampw), pdb_get_profile_path(sampw), pdb_get_logon_time(sampw), get_time_t_max(), get_time_t_max(), pdb_get_pass_last_set_time(sampw), pdb_get_pass_can_change_time(sampw), pdb_get_pass_must_change_time(sampw), 0, /* logon_count */ 0, /* bad_pw_count */ num_gids, /* uint32 num_groups */ gids , /* DOM_GID *gids */ 0x20 , /* uint32 user_flgs (?) */ server_info->user_session_key.length ? user_session_key : NULL, server_info->lm_session_key.length ? lm_session_key : NULL, my_name , /* char *logon_srv */ pdb_get_domain(sampw), &domain_sid, /* DOM_SID *dom_sid */ /* Should be users domain sid, not servers - for trusted domains */ NULL); /* char *other_sids */ ZERO_STRUCT(user_session_key); ZERO_STRUCT(lm_session_key); } free_server_info(&server_info); return status; }
int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name) { user_struct *vuser = NULL; /* Ensure no vuid gets registered in share level security. */ if(lp_security() == SEC_SHARE) { data_blob_free(&session_key); return UID_FIELD_INVALID; } /* Limit allowed vuids to 16bits - VUID_OFFSET. */ if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) { data_blob_free(&session_key); return UID_FIELD_INVALID; } if((vuser = SMB_MALLOC_P(user_struct)) == NULL) { DEBUG(0,("Failed to malloc users struct!\n")); data_blob_free(&session_key); return UID_FIELD_INVALID; } ZERO_STRUCTP(vuser); /* Allocate a free vuid. Yes this is a linear search... :-) */ while( get_valid_user_struct(next_vuid) != NULL ) { next_vuid++; /* Check for vuid wrap. */ if (next_vuid == UID_FIELD_INVALID) next_vuid = VUID_OFFSET; } DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid )); vuser->vuid = next_vuid; /* the next functions should be done by a SID mapping system (SMS) as * the new real sam db won't have reference to unix uids or gids */ vuser->uid = server_info->uid; vuser->gid = server_info->gid; vuser->n_groups = server_info->n_groups; if (vuser->n_groups) { if (!(vuser->groups = memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) { DEBUG(0,("register_vuid: failed to memdup vuser->groups\n")); data_blob_free(&session_key); free(vuser); free_server_info(&server_info); return UID_FIELD_INVALID; } } vuser->guest = server_info->guest; fstrcpy(vuser->user.unix_name, server_info->unix_name); /* This is a potentially untrusted username */ alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name)); fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account)); fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account)); { /* Keep the homedir handy */ const char *homedir = pdb_get_homedir(server_info->sam_account); const char *logon_script = pdb_get_logon_script(server_info->sam_account); if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) { const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account); if (unix_homedir) { vuser->unix_homedir = smb_xstrdup(unix_homedir); } } else { struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name); if (passwd) { vuser->unix_homedir = smb_xstrdup(passwd->pw_dir); passwd_free(&passwd); } } if (homedir) { vuser->homedir = smb_xstrdup(homedir); } if (logon_script) { vuser->logon_script = smb_xstrdup(logon_script); } } vuser->session_key = session_key; DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->uid, (unsigned int)vuser->gid, vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest )); DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name)); if (server_info->ptok) { vuser->nt_user_token = dup_nt_token(server_info->ptok); } else { DEBUG(1, ("server_info does not contain a user_token - cannot continue\n")); free_server_info(&server_info); data_blob_free(&session_key); SAFE_FREE(vuser->homedir); SAFE_FREE(vuser->unix_homedir); SAFE_FREE(vuser->logon_script); SAFE_FREE(vuser); return UID_FIELD_INVALID; } /* use this to keep tabs on all our info from the authentication */ vuser->server_info = server_info; DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid)); next_vuid++; num_validated_vuids++; DLIST_ADD(validated_users, vuser); if (!session_claim(vuser)) { DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid)); invalidate_vuid(vuser->vuid); return -1; } /* Register a home dir service for this user iff (a) This is not a guest connection, (b) we have a home directory defined (c) there s not an existing static share by that name If a share exists by this name (autoloaded or not) reuse it . */ vuser->homes_snum = -1; if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) { int servicenumber = lp_servicenumber(vuser->user.unix_name); if ( servicenumber == -1 ) { DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", vuser->user.unix_name, vuser->unix_homedir)); vuser->homes_snum = add_home_service(vuser->user.unix_name, vuser->user.unix_name, vuser->unix_homedir); } else { DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", vuser->user.unix_name, lp_pathname(servicenumber) )); vuser->homes_snum = servicenumber; } } if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) { /* Try and turn on server signing on the first non-guest sessionsetup. */ srv_set_signing(vuser->session_key, response_blob); } /* fill in the current_user_info struct */ set_current_user_info( &vuser->user ); return vuser->vuid; }