예제 #1
0
void buildSmbNtlmAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, char *user, char *password)
  {
    uint8 lmRespData[24];
    uint8 ntRespData[24];
    char *d = strdup(GetUnicodeString(challenge,uDomain));
    char *domain = d;
    char *u = strdup(user);
    char *p = strchr(u,'@');
    
    if (p)
      {
        domain = p+1;
        *p = '\0';
      }
    
    SMBencrypt(password,   challenge->challengeData, lmRespData);
    SMBNTencrypt(password, challenge->challengeData, ntRespData);
    
    response->bufIndex = 0;
    memcpy(response->ident,"NTLMSSP\0\0\0",8);
    SIVAL(&response->msgType,0,3);
    
    AddBytes(response,lmResponse,lmRespData,24);
    AddBytes(response,ntResponse,ntRespData,24);
    AddUnicodeString(response,uDomain,domain);
    AddUnicodeString(response,uUser,u);
    AddUnicodeString(response,uWks,u);
    AddString(response,sessionKey,NULL);
  
    response->flags = challenge->flags;
    
    free(d);
    free(u);
  }
예제 #2
0
/* returns 0 on success, > 0 on failure */
static int
init_challenge(char *domain, char *domain_controller)
{
    int smberr;

    if (handle != NULL) {
	return 0;
    }
    debug("Connecting to server %s domain %s\n", domain_controller, domain);
    handle = SMB_Connect_Server(NULL, domain_controller, domain);
    smberr = SMB_Get_Last_Error();
    SMB_Get_Error_Msg(smberr, errstr, 1000);


    if (handle == NULL) {	/* couldn't connect */
	debug("Couldn't connect to SMB Server. Error:%s\n", errstr);
	return 1;
    }
    if (SMB_Negotiate(handle, SMB_Prots) < 0) {		/* An error */
	debug("Error negotiating protocol with SMB Server\n");
	SMB_Discon(handle, 0);
	handle = NULL;
	return 2;
    }
    if (handle->Security == 0) {	/* share-level security, unuseable */
	debug("SMB Server uses share-level security .. we need user security.\n");
	SMB_Discon(handle, 0);
	handle = NULL;
	return 3;
    }
    memcpy(challenge, handle->Encrypt_Key, NONCE_LEN);
		SMBencrypt((unsigned char *)"",challenge,lmencoded_empty_pass);
		SMBNTencrypt((unsigned char *)"",challenge,ntencoded_empty_pass);
    return 0;
}
예제 #3
0
파일: py_winbind.c 프로젝트: hajuuk/R7000
static PyObject *py_auth_smbd(PyObject *self, PyObject *args, PyObject *kw)
{
	static char *kwlist[] = 
		{"username", "password", "use_lm_hash", "use_nt_hash", NULL };
	struct winbindd_request request;
	struct winbindd_response response;
	char *username, *password;
	int use_lm_hash = 1, use_nt_hash = 1;

	if (!PyArg_ParseTupleAndKeywords(
		    args, kw, "ss|ii", kwlist, &username, &password, 
		    &use_lm_hash, &use_nt_hash))
		return NULL;

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

	if (push_utf8_fstring(request.data.auth_crap.user, username) == -1) {
		PyErr_SetString("unable to create utf8 string");
		return NULL;
	}

	generate_random_buffer(request.data.smbd_auth_crap.chal, 8);
        
	if (use_lm_hash) {
		SMBencrypt((uchar *)password, 
			   request.data.smbd_auth_crap.chal, 
			   (uchar *)request.data.smbd_auth_crap.lm_resp);
		request.data.smbd_auth_crap.lm_resp_len = 24;
	}

	if (use_nt_hash) {
		SMBNTencrypt((uchar *)password, 
			     request.data.smbd_auth_crap.chal,
			     (uchar *)request.data.smbd_auth_crap.nt_resp);
		request.data.smbd_auth_crap.nt_resp_len = 24;
	}

	if (!secrets_fetch_trust_account_password(
		    lp_workgroup(), request.data.smbd_auth_crap.proof, NULL)) {
		PyErr_SetString(
			winbind_error, "unable to fetch domain secret");
		return NULL;
	}



	if (winbindd_request(WINBINDD_SMBD_AUTH_CRAP, &request, &response) 
	    != NSS_STATUS_SUCCESS) {
		PyErr_SetString(winbind_error, "lookup failed");
		return NULL;		
	}
	
	return PyInt_FromLong(response.data.auth.nt_status);
}
예제 #4
0
/* first calculate 24 bytes ntlm response and then 16 byte session key */
int setup_ntlm_response(struct cifsSesInfo *ses)
{
	unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
	char temp_key[CIFS_SESS_KEY_SIZE];

	if (!ses)
		return -EINVAL;

	ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
	if (!ses->auth_key.response) {
		cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len);
		return -ENOMEM;
	}
	ses->auth_key.len = temp_len;

	SMBNTencrypt(ses->password, ses->server->cryptkey,
			ses->auth_key.response + CIFS_SESS_KEY_SIZE);

	E_md4hash(ses->password, temp_key);
	mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);

	return 0;
}
예제 #5
0
/* first calculate 24 bytes ntlm response and then 16 byte session key */
int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp)
{
	int rc = 0;
	unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
	char temp_key[CIFS_SESS_KEY_SIZE];

	if (!ses)
		return -EINVAL;

	ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
	if (!ses->auth_key.response)
		return -ENOMEM;

	ses->auth_key.len = temp_len;

	rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
			ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp);
	if (rc) {
		cifs_dbg(FYI, "%s Can't generate NTLM response, error: %d\n",
			 __func__, rc);
		return rc;
	}

	rc = E_md4hash(ses->password, temp_key, nls_cp);
	if (rc) {
		cifs_dbg(FYI, "%s Can't generate NT hash, error: %d\n",
			 __func__, rc);
		return rc;
	}

	rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
	if (rc)
		cifs_dbg(FYI, "%s Can't generate NTLM session key, error: %d\n",
			 __func__, rc);

	return rc;
}
예제 #6
0
/* first calculate 24 bytes ntlm response and then 16 byte session key */
int setup_ntlm_response(struct cifsSesInfo *ses)
{
	int rc = 0;
	unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE;
	char temp_key[CIFS_SESS_KEY_SIZE];

	if (!ses)
		return -EINVAL;

	ses->auth_key.response = kmalloc(temp_len, GFP_KERNEL);
	if (!ses->auth_key.response) {
		cERROR(1, "NTLM can't allocate (%u bytes) memory", temp_len);
		return -ENOMEM;
	}
	ses->auth_key.len = temp_len;

	rc = SMBNTencrypt(ses->password, ses->server->cryptkey,
			ses->auth_key.response + CIFS_SESS_KEY_SIZE);
	if (rc) {
		cFYI(1, "%s Can't generate NTLM response, error: %d",
			__func__, rc);
		return rc;
	}

	rc = E_md4hash(ses->password, temp_key);
	if (rc) {
		cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc);
		return rc;
	}

	rc = mdfour(ses->auth_key.response, temp_key, CIFS_SESS_KEY_SIZE);
	if (rc)
		cFYI(1, "%s Can't generate NTLM session key, error: %d",
			__func__, rc);

	return rc;
}
예제 #7
0
static bool test_lm_ntlm_broken(enum ntlm_break break_which) 
{
	bool pass = True;
	NTSTATUS nt_status;
	uint32 flags = 0;
	DATA_BLOB lm_response = data_blob(NULL, 24);
	DATA_BLOB nt_response = data_blob(NULL, 24);
	DATA_BLOB session_key = data_blob(NULL, 16);

	uchar lm_key[8];
	uchar user_session_key[16];
	uchar lm_hash[16];
	uchar nt_hash[16];
	DATA_BLOB chall = get_challenge();
	char *error_string;
	
	ZERO_STRUCT(lm_key);
	ZERO_STRUCT(user_session_key);

	flags |= WBFLAG_PAM_LMKEY;
	flags |= WBFLAG_PAM_USER_SESSION_KEY;

	SMBencrypt(opt_password,chall.data,lm_response.data);
	E_deshash(opt_password, lm_hash); 

	SMBNTencrypt(opt_password,chall.data,nt_response.data);

	E_md4hash(opt_password, nt_hash);
	SMBsesskeygen_ntv1(nt_hash, session_key.data);

	switch (break_which) {
	case BREAK_NONE:
		break;
	case BREAK_LM:
		lm_response.data[0]++;
		break;
	case BREAK_NT:
		nt_response.data[0]++;
		break;
	case NO_LM:
		data_blob_free(&lm_response);
		break;
	case NO_NT:
		data_blob_free(&nt_response);
		break;
	}

	nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
					      opt_workstation,
					      &chall,
					      &lm_response,
					      &nt_response,
					      flags,
					      lm_key, 
					      user_session_key,
					      &error_string, NULL);
	
	data_blob_free(&lm_response);

	if (!NT_STATUS_IS_OK(nt_status)) {
		d_printf("%s (0x%x)\n", 
			 error_string,
			 NT_STATUS_V(nt_status));
		SAFE_FREE(error_string);
		return break_which == BREAK_NT;
	}

	if (memcmp(lm_hash, lm_key, 
		   sizeof(lm_key)) != 0) {
		DEBUG(1, ("LM Key does not match expectations!\n"));
 		DEBUG(1, ("lm_key:\n"));
		dump_data(1, lm_key, 8);
		DEBUG(1, ("expected:\n"));
		dump_data(1, lm_hash, 8);
		pass = False;
	}

	if (break_which == NO_NT) {
		if (memcmp(lm_hash, user_session_key, 
			   8) != 0) {
			DEBUG(1, ("NT Session Key does not match expectations (should be LM hash)!\n"));
			DEBUG(1, ("user_session_key:\n"));
			dump_data(1, user_session_key, sizeof(user_session_key));
			DEBUG(1, ("expected:\n"));
			dump_data(1, lm_hash, sizeof(lm_hash));
			pass = False;
		}
	} else {		
		if (memcmp(session_key.data, user_session_key, 
			   sizeof(user_session_key)) != 0) {
			DEBUG(1, ("NT Session Key does not match expectations!\n"));
			DEBUG(1, ("user_session_key:\n"));
			dump_data(1, user_session_key, 16);
			DEBUG(1, ("expected:\n"));
			dump_data(1, session_key.data, session_key.length);
			pass = False;
		}
	}
        return pass;
}
예제 #8
0
static bool test_ntlm_in_both(void) 
{
	bool pass = True;
	NTSTATUS nt_status;
	uint32 flags = 0;
	DATA_BLOB nt_response = data_blob(NULL, 24);
	DATA_BLOB session_key = data_blob(NULL, 16);

	uint8 lm_key[8];
	uint8 lm_hash[16];
	uint8 user_session_key[16];
	uint8 nt_hash[16];
	DATA_BLOB chall = get_challenge();
	char *error_string;
	
	ZERO_STRUCT(lm_key);
	ZERO_STRUCT(user_session_key);

	flags |= WBFLAG_PAM_LMKEY;
	flags |= WBFLAG_PAM_USER_SESSION_KEY;

	SMBNTencrypt(opt_password,chall.data,nt_response.data);
	E_md4hash(opt_password, nt_hash);
	SMBsesskeygen_ntv1(nt_hash, session_key.data);

	E_deshash(opt_password, lm_hash); 

	nt_status = contact_winbind_auth_crap(opt_username, opt_domain, 
					      opt_workstation,
					      &chall,
					      &nt_response,
					      &nt_response,
					      flags,
					      lm_key,
					      user_session_key,
					      &error_string, NULL);
	
	data_blob_free(&nt_response);

	if (!NT_STATUS_IS_OK(nt_status)) {
		d_printf("%s (0x%x)\n", 
			 error_string,
			 NT_STATUS_V(nt_status));
		SAFE_FREE(error_string);
		return False;
	}

	if (memcmp(lm_hash, lm_key, 
		   sizeof(lm_key)) != 0) {
		DEBUG(1, ("LM Key does not match expectations!\n"));
 		DEBUG(1, ("lm_key:\n"));
		dump_data(1, lm_key, 8);
		DEBUG(1, ("expected:\n"));
		dump_data(1, lm_hash, 8);
		pass = False;
	}
	if (memcmp(session_key.data, user_session_key, 
		   sizeof(user_session_key)) != 0) {
		DEBUG(1, ("NT Session Key does not match expectations!\n"));
 		DEBUG(1, ("user_session_key:\n"));
		dump_data(1, user_session_key, 16);
 		DEBUG(1, ("expected:\n"));
		dump_data(1, session_key.data, session_key.length);
		pass = False;
	}


        return pass;
}
예제 #9
0
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state) 
{
	NTSTATUS result;
	fstring name_domain, name_user;
	unsigned char trust_passwd[16];
	time_t last_change_time;
	uint32 sec_channel_type;
        NET_USER_INFO_3 info3;
        struct cli_state *cli = NULL;
	uchar chal[8];
	TALLOC_CTX *mem_ctx = NULL;
	DATA_BLOB lm_resp;
	DATA_BLOB nt_resp;
	DOM_CRED ret_creds;
	int attempts = 0;
	unsigned char local_lm_response[24];
	unsigned char local_nt_response[24];
	struct winbindd_domain *contact_domain;
	BOOL retry;

	/* Ensure null termination */
	state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';

	/* Ensure null termination */
	state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';

	DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
		  state->request.data.auth.user));

	if (!(mem_ctx = talloc_init("winbind pam auth for %s", state->request.data.auth.user))) {
		DEBUG(0, ("winbindd_pam_auth: could not talloc_init()!\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* Parse domain and username */
	
	parse_domain_user(state->request.data.auth.user, name_domain, name_user);

	/* do password magic */
	
	generate_random_buffer(chal, 8);
	SMBencrypt(state->request.data.auth.pass, chal, local_lm_response);
		
	SMBNTencrypt(state->request.data.auth.pass, chal, local_nt_response);

	lm_resp = data_blob_talloc(mem_ctx, local_lm_response, sizeof(local_lm_response));
	nt_resp = data_blob_talloc(mem_ctx, local_nt_response, sizeof(local_nt_response));
	
	/* what domain should we contact? */
	
	if ( IS_DC ) {
		if (!(contact_domain = find_domain_from_name(name_domain))) {
			DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
				  state->request.data.auth.user, name_domain, name_user, name_domain)); 
			result = NT_STATUS_NO_SUCH_USER;
			goto done;
		}
		
	} else {
		if (is_myname(name_domain)) {
			DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
			result =  NT_STATUS_NO_SUCH_USER;
			goto done;
		}

		if (!(contact_domain = find_our_domain())) {
			DEBUG(1, ("Authentication for [%s] -> [%s]\\[%s] in our domain failed - we can't find our domain!\n", 
				  state->request.data.auth.user, name_domain, name_user)); 
			result = NT_STATUS_NO_SUCH_USER;
			goto done;
		}
	}

	if ( !get_trust_pw(contact_domain->name, trust_passwd, &last_change_time, &sec_channel_type) ) {
		result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
		goto done;
	}

	/* check authentication loop */

	do {
		ZERO_STRUCT(info3);
		ZERO_STRUCT(ret_creds);
		retry = False;
	
		/* Don't shut this down - it belongs to the connection cache code */
		result = cm_get_netlogon_cli(contact_domain, trust_passwd, 
					     sec_channel_type, False, &cli);

		if (!NT_STATUS_IS_OK(result)) {
			DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
			goto done;
		}

		result = cli_netlogon_sam_network_logon(cli, mem_ctx,
							&ret_creds,
							name_user, name_domain, 
							global_myname(), chal, 
							lm_resp, nt_resp,
							&info3);
		attempts += 1;
		
		/* We have to try a second time as cm_get_netlogon_cli
		   might not yet have noticed that the DC has killed
		   our connection. */

		if ( cli->fd == -1 ) {
			retry = True;
			continue;
		} 
		
		/* if we get access denied, a possible cuase was that we had and open
		   connection to the DC, but someone changed our machine account password
		   out from underneath us using 'net rpc changetrustpw' */
		   
		if ( NT_STATUS_V(result) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) {
			DEBUG(3,("winbindd_pam_auth: sam_logon returned ACCESS_DENIED.  Maybe the trust account "
				"password was changed and we didn't know it.  Killing connections to domain %s\n",
				name_domain));
			winbindd_cm_flush();
			retry = True;
			cli = NULL;
		} 
		
	} while ( (attempts < 2) && retry );

        if (cli != NULL) {
		/* We might have come out of the loop above with cli == NULL,
		   so don't dereference that. */
		clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds);
	}
	
	if (NT_STATUS_IS_OK(result)) {
		netsamlogon_cache_store( cli->mem_ctx, &info3 );
		wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);

		/* Check if the user is in the right group */

		if (!NT_STATUS_IS_OK(result = check_info3_in_group(mem_ctx, &info3, state->request.data.auth.required_membership_sid))) {
			DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
				  state->request.data.auth.user, 
				  state->request.data.auth.required_membership_sid));
		}
	}

done:
	/* give us a more useful (more correct?) error code */
	if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
		result = NT_STATUS_NO_LOGON_SERVERS;
	}
	
	state->response.data.auth.nt_status = NT_STATUS_V(result);
	fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));

	/* we might have given a more useful error above */
	if (!*state->response.data.auth.error_string) 
		fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
	state->response.data.auth.pam_error = nt_status_to_pam(result);

	DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, ("Plain-text authentication for user %s returned %s (PAM: %d)\n", 
	      state->request.data.auth.user, 
	      state->response.data.auth.nt_status_string,
	      state->response.data.auth.pam_error));	      

	if ( NT_STATUS_IS_OK(result) &&
	     (state->request.flags & WBFLAG_PAM_AFS_TOKEN) ) {

		char *afsname = strdup(lp_afs_username_map());
		char *cell;

		if (afsname == NULL) goto no_token;

		afsname = realloc_string_sub(afsname, "%D", name_domain);
		afsname = realloc_string_sub(afsname, "%u", name_user);
		afsname = realloc_string_sub(afsname, "%U", name_user);

		if (afsname == NULL) goto no_token;

		strlower_m(afsname);

		cell = strchr(afsname, '@');

		if (cell == NULL) goto no_token;

		*cell = '\0';
		cell += 1;

		/* Append an AFS token string */
		state->response.extra_data =
			afs_createtoken_str(afsname, cell);

		if (state->response.extra_data != NULL)
			state->response.length +=
				strlen(state->response.extra_data)+1;

	no_token:
		SAFE_FREE(afsname);
	}
		
	if (mem_ctx) 
		talloc_destroy(mem_ctx);
	
	return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
예제 #10
0
파일: wbinfo4.c 프로젝트: gojdic/samba
static bool wbinfo_auth_crap(struct loadparm_context *lp_ctx, char *username)
{
	struct winbindd_request request;
	struct winbindd_response response;
        NSS_STATUS result;
        fstring name_user;
        fstring name_domain;
        fstring pass;
        char *p;

	/* Send off request */

	ZERO_STRUCT(request);
	ZERO_STRUCT(response);

        p = strchr(username, '%');

        if (p) {
                *p = 0;
                fstrcpy(pass, p + 1);
	}

	parse_wbinfo_domain_user(username, name_domain, name_user);

	request.data.auth_crap.logon_parameters = MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT | MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;

	fstrcpy(request.data.auth_crap.user, name_user);

	fstrcpy(request.data.auth_crap.domain,
			      name_domain);

	generate_random_buffer(request.data.auth_crap.chal, 8);

	if (lp_client_ntlmv2_auth(lp_ctx)) {
		DATA_BLOB server_chal;
		DATA_BLOB names_blob;

		DATA_BLOB lm_response;
		DATA_BLOB nt_response;

		TALLOC_CTX *mem_ctx;
		mem_ctx = talloc_new(NULL);
		if (mem_ctx == NULL) {
			d_printf("talloc_new failed\n");
			return false;
		}

		server_chal = data_blob(request.data.auth_crap.chal, 8);

		/* Pretend this is a login to 'us', for blob purposes */
		names_blob = NTLMv2_generate_names_blob(mem_ctx, lp_netbios_name(lp_ctx), lp_workgroup(lp_ctx));

		if (!SMBNTLMv2encrypt(mem_ctx, name_user, name_domain, pass, &server_chal,
				      &names_blob,
				      &lm_response, &nt_response, NULL, NULL)) {
			data_blob_free(&names_blob);
			data_blob_free(&server_chal);
			return false;
		}
		data_blob_free(&names_blob);
		data_blob_free(&server_chal);

		memcpy(request.data.auth_crap.nt_resp, nt_response.data,
		       MIN(nt_response.length,
			   sizeof(request.data.auth_crap.nt_resp)));
		request.data.auth_crap.nt_resp_len = nt_response.length;

		memcpy(request.data.auth_crap.lm_resp, lm_response.data,
		       MIN(lm_response.length,
			   sizeof(request.data.auth_crap.lm_resp)));
		request.data.auth_crap.lm_resp_len = lm_response.length;

		data_blob_free(&nt_response);
		data_blob_free(&lm_response);

	} else {
		if (lp_client_lanman_auth(lp_ctx)
		    && SMBencrypt(pass, request.data.auth_crap.chal,
			       (unsigned char *)request.data.auth_crap.lm_resp)) {
			request.data.auth_crap.lm_resp_len = 24;
		} else {
			request.data.auth_crap.lm_resp_len = 0;
		}
		SMBNTencrypt(pass, request.data.auth_crap.chal,
			     (unsigned char *)request.data.auth_crap.nt_resp);

		request.data.auth_crap.nt_resp_len = 24;
	}

	result = winbindd_request_response(WINBINDD_PAM_AUTH_CRAP, &request, &response);

	/* Display response */

        d_printf("challenge/response password authentication %s\n",
               (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed");

	if (response.data.auth.nt_status)
		d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
			 response.data.auth.nt_status_string,
			 response.data.auth.nt_status,
			 response.data.auth.error_string);

        return result == NSS_STATUS_SUCCESS;
}
예제 #11
0
파일: sess.c 프로젝트: 274914765/C
int
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
        const struct nls_table *nls_cp)
{
    int rc = 0;
    int wct;
    struct smb_hdr *smb_buf;
    char *bcc_ptr;
    char *str_area;
    SESSION_SETUP_ANDX *pSMB;
    __u32 capabilities;
    int count;
    int resp_buf_type;
    struct kvec iov[3];
    enum securityEnum type;
    __u16 action;
    int bytes_remaining;
    struct key *spnego_key = NULL;

    if (ses == NULL)
        return -EINVAL;

    type = ses->server->secType;

    cFYI(1, ("sess setup type %d", type));
    if (type == LANMAN) {
#ifndef CONFIG_CIFS_WEAK_PW_HASH
        /* LANMAN and plaintext are less secure and off by default.
        So we make this explicitly be turned on in kconfig (in the
        build) and turned on at runtime (changed from the default)
        in proc/fs/cifs or via mount parm.  Unfortunately this is
        needed for old Win (e.g. Win95), some obscure NAS and OS/2 */
        return -EOPNOTSUPP;
#endif
        wct = 10; /* lanman 2 style sessionsetup */
    } else if ((type == NTLM) || (type == NTLMv2)) {
        /* For NTLMv2 failures eventually may need to retry NTLM */
        wct = 13; /* old style NTLM sessionsetup */
    } else /* same size: negotiate or auth, NTLMSSP or extended security */
        wct = 12;

    rc = small_smb_init_no_tc(SMB_COM_SESSION_SETUP_ANDX, wct, ses,
                (void **)&smb_buf);
    if (rc)
        return rc;

    pSMB = (SESSION_SETUP_ANDX *)smb_buf;

    capabilities = cifs_ssetup_hdr(ses, pSMB);

    /* we will send the SMB in three pieces:
    a fixed length beginning part, an optional
    SPNEGO blob (which can be zero length), and a
    last part which will include the strings
    and rest of bcc area. This allows us to avoid
    a large buffer 17K allocation */
    iov[0].iov_base = (char *)pSMB;
    iov[0].iov_len = smb_buf->smb_buf_length + 4;

    /* setting this here allows the code at the end of the function
       to free the request buffer if there's an error */
    resp_buf_type = CIFS_SMALL_BUFFER;

    /* 2000 big enough to fit max user, domain, NOS name etc. */
    str_area = kmalloc(2000, GFP_KERNEL);
    if (str_area == NULL) {
        rc = -ENOMEM;
        goto ssetup_exit;
    }
    bcc_ptr = str_area;

    ses->flags &= ~CIFS_SES_LANMAN;

    iov[1].iov_base = NULL;
    iov[1].iov_len = 0;

    if (type == LANMAN) {
#ifdef CONFIG_CIFS_WEAK_PW_HASH
        char lnm_session_key[CIFS_SESS_KEY_SIZE];

        /* no capabilities flags in old lanman negotiation */

        pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_SESS_KEY_SIZE);
        /* BB calculate hash with password */
        /* and copy into bcc */

        calc_lanman_hash(ses, lnm_session_key);
        ses->flags |= CIFS_SES_LANMAN;
        memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_SESS_KEY_SIZE);
        bcc_ptr += CIFS_SESS_KEY_SIZE;

        /* can not sign if LANMAN negotiated so no need
        to calculate signing key? but what if server
        changed to do higher than lanman dialect and
        we reconnected would we ever calc signing_key? */

        cFYI(1, ("Negotiating LANMAN setting up strings"));
        /* Unicode not allowed for LANMAN dialects */
        ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
#endif
    } else if (type == NTLM) {
        char ntlm_session_key[CIFS_SESS_KEY_SIZE];

        pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
        pSMB->req_no_secext.CaseInsensitivePasswordLength =
            cpu_to_le16(CIFS_SESS_KEY_SIZE);
        pSMB->req_no_secext.CaseSensitivePasswordLength =
            cpu_to_le16(CIFS_SESS_KEY_SIZE);

        /* calculate session key */
        SMBNTencrypt(ses->password, ses->server->cryptKey,
                 ntlm_session_key);

        if (first_time) /* should this be moved into common code
                  with similar ntlmv2 path? */
            cifs_calculate_mac_key(&ses->server->mac_signing_key,
                ntlm_session_key, ses->password);
        /* copy session key */

        memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
        bcc_ptr += CIFS_SESS_KEY_SIZE;
        memcpy(bcc_ptr, (char *)ntlm_session_key, CIFS_SESS_KEY_SIZE);
        bcc_ptr += CIFS_SESS_KEY_SIZE;
        if (ses->capabilities & CAP_UNICODE) {
            /* unicode strings must be word aligned */
            if (iov[0].iov_len % 2) {
                *bcc_ptr = 0;
                bcc_ptr++;
            }
            unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
        } else
            ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
    } else if (type == NTLMv2) {
        char *v2_sess_key =
            kmalloc(sizeof(struct ntlmv2_resp), GFP_KERNEL);

        /* BB FIXME change all users of v2_sess_key to
           struct ntlmv2_resp */

        if (v2_sess_key == NULL) {
            rc = -ENOMEM;
            goto ssetup_exit;
        }

        pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);

        /* LM2 password would be here if we supported it */
        pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
        /*    cpu_to_le16(LM2_SESS_KEY_SIZE); */

        pSMB->req_no_secext.CaseSensitivePasswordLength =
            cpu_to_le16(sizeof(struct ntlmv2_resp));

        /* calculate session key */
        setup_ntlmv2_rsp(ses, v2_sess_key, nls_cp);
        if (first_time) /* should this be moved into common code
                   with similar ntlmv2 path? */
        /*   cifs_calculate_ntlmv2_mac_key(ses->server->mac_signing_key,
                response BB FIXME, v2_sess_key); */

        /* copy session key */

    /*    memcpy(bcc_ptr, (char *)ntlm_session_key,LM2_SESS_KEY_SIZE);
        bcc_ptr += LM2_SESS_KEY_SIZE; */
        memcpy(bcc_ptr, (char *)v2_sess_key,
               sizeof(struct ntlmv2_resp));
        bcc_ptr += sizeof(struct ntlmv2_resp);
        kfree(v2_sess_key);
        if (ses->capabilities & CAP_UNICODE) {
            if (iov[0].iov_len % 2) {
                *bcc_ptr = 0;
                bcc_ptr++;
            }
            unicode_ssetup_strings(&bcc_ptr, ses, nls_cp);
        } else
            ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
    } else if (type == Kerberos) {
#ifdef CONFIG_CIFS_UPCALL
        struct cifs_spnego_msg *msg;
        spnego_key = cifs_get_spnego_key(ses);
        if (IS_ERR(spnego_key)) {
            rc = PTR_ERR(spnego_key);
            spnego_key = NULL;
            goto ssetup_exit;
        }

        msg = spnego_key->payload.data;
        /* bail out if key is too long */
        if (msg->sesskey_len >
            sizeof(ses->server->mac_signing_key.data.krb5)) {
            cERROR(1, ("Kerberos signing key too long (%u bytes)",
                msg->sesskey_len));
            rc = -EOVERFLOW;
            goto ssetup_exit;
        }
        if (first_time) {
            ses->server->mac_signing_key.len = msg->sesskey_len;
            memcpy(ses->server->mac_signing_key.data.krb5,
                msg->data, msg->sesskey_len);
        }
        pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
        capabilities |= CAP_EXTENDED_SECURITY;
        pSMB->req.Capabilities = cpu_to_le32(capabilities);
        iov[1].iov_base = msg->data + msg->sesskey_len;
        iov[1].iov_len = msg->secblob_len;
        pSMB->req.SecurityBlobLength = cpu_to_le16(iov[1].iov_len);

        if (ses->capabilities & CAP_UNICODE) {
            /* unicode strings must be word aligned */
            if ((iov[0].iov_len + iov[1].iov_len) % 2) {
                *bcc_ptr = 0;
                bcc_ptr++;
            }
            unicode_oslm_strings(&bcc_ptr, nls_cp);
            unicode_domain_string(&bcc_ptr, ses, nls_cp);
        } else
        /* BB: is this right? */
            ascii_ssetup_strings(&bcc_ptr, ses, nls_cp);
#else /* ! CONFIG_CIFS_UPCALL */
        cERROR(1, ("Kerberos negotiated but upcall support disabled!"));
        rc = -ENOSYS;
        goto ssetup_exit;
#endif /* CONFIG_CIFS_UPCALL */
    } else {
        cERROR(1, ("secType %d not supported!", type));
        rc = -ENOSYS;
        goto ssetup_exit;
    }

    iov[2].iov_base = str_area;
    iov[2].iov_len = (long) bcc_ptr - (long) str_area;

    count = iov[1].iov_len + iov[2].iov_len;
    smb_buf->smb_buf_length += count;

    BCC_LE(smb_buf) = cpu_to_le16(count);

    rc = SendReceive2(xid, ses, iov, 3 /* num_iovecs */, &resp_buf_type,
              CIFS_STD_OP /* not long */ | CIFS_LOG_ERROR);
    /* SMB request buf freed in SendReceive2 */

    cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
    if (rc)
        goto ssetup_exit;

    pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
    smb_buf = (struct smb_hdr *)iov[0].iov_base;

    if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
        rc = -EIO;
        cERROR(1, ("bad word count %d", smb_buf->WordCount));
        goto ssetup_exit;
    }
    action = le16_to_cpu(pSMB->resp.Action);
    if (action & GUEST_LOGIN)
        cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
    ses->Suid = smb_buf->Uid;   /* UID left in wire format (le) */
    cFYI(1, ("UID = %d ", ses->Suid));
    /* response can have either 3 or 4 word count - Samba sends 3 */
    /* and lanman response is 3 */
    bytes_remaining = BCC(smb_buf);
    bcc_ptr = pByteArea(smb_buf);

    if (smb_buf->WordCount == 4) {
        __u16 blob_len;
        blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
        bcc_ptr += blob_len;
        if (blob_len > bytes_remaining) {
            cERROR(1, ("bad security blob length %d", blob_len));
            rc = -EINVAL;
            goto ssetup_exit;
        }
        bytes_remaining -= blob_len;
    }

    /* BB check if Unicode and decode strings */
    if (smb_buf->Flags2 & SMBFLG2_UNICODE)
        rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
                           ses, nls_cp);
    else
        rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
                     ses, nls_cp);

ssetup_exit:
    if (spnego_key)
        key_put(spnego_key);
    kfree(str_area);
    if (resp_buf_type == CIFS_SMALL_BUFFER) {
        cFYI(1, ("ssetup freeing small buf %p", iov[0].iov_base));
        cifs_small_buf_release(iov[0].iov_base);
    } else if (resp_buf_type == CIFS_LARGE_BUFFER)
        cifs_buf_release(iov[0].iov_base);

    return rc;
}
예제 #12
0
BOOL cli_session_setup(struct cli_state *cli,
		       char *_user,
		       char *pass, int passlen,
		       char *ntpass, int ntpasslen, char *_workgroup)
{
	fstring pword, ntpword;
	fstring user;
	fstring workgroup;
	uint8 protocol;
	SMB_HDR hdr;

	Q_SESSION_SETUP_ANDX qw;
	R_SESSION_SETUP_ANDX rw;
	Q_SESSION_SETUP_ANDX_D qd;
	R_SESSION_SETUP_ANDX_D rd;

	ZERO_STRUCT(qw);
	ZERO_STRUCT(rw);
	ZERO_STRUCT(qd);
	ZERO_STRUCT(rd);

	ZERO_STRUCT(pword);
	ZERO_STRUCT(ntpword);

	if (!smb_get_protocol(cli->hnd, &protocol))
		return False;

	if (protocol < PROTOCOL_LANMAN1)
		return True;

	if (passlen > sizeof(pword) - 1 || ntpasslen > sizeof(ntpword) - 1)
	{
		return False;
	}

	if (((passlen == 0) || (passlen == 1)) && (pass[0] == '\0'))
	{
		/* Null session connect. */
		pword[0] = '\0';
		ntpword[0] = '\0';
		passlen = 1;
		_user = "";
	}
	else if ((cli->sec_mode & 2) && passlen != 24)
	{
		/*
		 * Encrypted mode needed, and non encrypted password supplied.
		 */
		passlen = 24;
		ntpasslen = 24;
		fstrcpy(pword, pass);
		unix_to_dos(pword, True);
		fstrcpy(ntpword, ntpass);;
		unix_to_dos(ntpword, True);
		SMBencrypt((uchar *) pword, (uchar *) cli->cryptkey,
			   (uchar *) pword);
		SMBNTencrypt((uchar *) ntpword, (uchar *) cli->cryptkey,
			     (uchar *) ntpword);
	}
	else if ((cli->sec_mode & 2) && passlen == 24)
	{
		/*
		 * Encrypted mode needed, and encrypted password supplied.
		 */
		memcpy(pword, pass, passlen);
		if (ntpasslen == 24)
		{
			memcpy(ntpword, ntpass, ntpasslen);
		}
		else
		{
			fstrcpy(ntpword, "");
			ntpasslen = 0;
		}
	}
	else
	{
		/*
		 * Plaintext mode needed, assume plaintext supplied.
		 */
		fstrcpy(pword, pass);
		unix_to_dos(pword, True);
		fstrcpy(ntpword, "");
		ntpasslen = 0;
	}

	/* if in share level security then don't send a password now */
	if (!(cli->sec_mode & 1))
	{
		fstrcpy(pword, "");
		passlen = 1;
		fstrcpy(ntpword, "");
		ntpasslen = 1;
	}

	fstrcpy(user, _user);
	fstrcpy(workgroup, _workgroup);

	/* send a session setup command */

	if (protocol < PROTOCOL_NT1)
	{
		Q_SESSION_SETUP_ANDX_D_10 *q10 = &qd.ctr.q10;
		Q_SESSION_SETUP_ANDX_10 *qs = &qw.ctr.q10;
		qw.wcount = 10;
		qd.wcount = 10;

		qs->andx.cmd = 0xff;
		qs->bufsize = cli->max_xmit;
		qs->max_mpx = 2;
		qs->vc = 1;
		qs->sess_key = cli->sesskey;
		qs->pwlen = passlen;

		q10->password = pword;
		q10->pwlen = passlen;
		smbstr_initA(&q10->user, user, 0);
		smbstr_initA(&q10->domain, workgroup, 0);
		smbstr_initA(&q10->os, "Unix", 0);
		smbstr_initA(&q10->server, "Samba", 0);
		smbstr_initA(&q10->pad1, "", 0);
		smbstr_initA(&q10->pad2, "", 0);
	}
	else
	{
		Q_SESSION_SETUP_ANDX_D_13 *q13 = &qd.ctr.q13;
		Q_SESSION_SETUP_ANDX_13 *qs = &qw.ctr.q13;

		qw.wcount = 13;
		qd.wcount = 13;

		qs->andx.cmd = 0xff;
		qs->bufsize = CLI_BUFFER_SIZE;
		qs->max_mpx = 2;
		smb_get_pid(cli->hnd, &qs->vc);
		qs->sess_key = cli->sesskey;
		qs->pwlen = passlen;
		qs->upwlen = ntpasslen;
		qs->capabilities = 0;

		q13->password = pword;
		q13->upassword = ntpword;
		q13->pwlen = passlen;
		q13->upwlen = ntpasslen;

		smbstr_initA(&q13->user, user, 0);
		smbstr_initA(&q13->domain, workgroup, 0);
		smbstr_initA(&q13->os, "Unix", 0);
		smbstr_initA(&q13->server, "Samba", 0);
		smbstr_initA(&q13->pad1, "", 0);
		smbstr_initA(&q13->pad2, "", 0);
	}

	cli->nterr = cli_SMBsesssetupX(cli->hnd, &qw, &rw, &qd, &rd, NULL, NULL);
	if (cli->nterr != 0)
		return False;

	if (!smb_get_hdr(cli->hnd, &hdr))
		return False;

	/*
	 * Save off some of the connected server
	 * info.
	 */
	if (protocol >= PROTOCOL_NT1 && rw.wcount == 3)
	{
		R_SESSION_SETUP_ANDX_D_3 *sd = &rd.ctr.d3;

		fstrcpy(cli->server_os, smbstrA(&sd->os));
		fstrcpy(cli->server_type, smbstrA(&sd->server));
		fstrcpy(cli->server_domain, smbstrA(&sd->domain));
	}

	fstrcpy(cli->user_name, user);
	dos_to_unix(cli->user_name, True);

	return True;
}
예제 #13
0
파일: cliconnect.c 프로젝트: jophxy/samba
static BOOL cli_session_setup_nt1(struct cli_state *cli, const char *user, 
				  const char *pass, int passlen,
				  const char *ntpass, int ntpasslen,
				  const char *workgroup)
{
	uint32 capabilities = cli_session_setup_capabilities(cli);
	fstring pword, ntpword;
	char *p;

	if (passlen > sizeof(pword)-1 || ntpasslen > sizeof(ntpword)-1) {
		return False;
	}

	if (passlen != 24) {
		/* non encrypted password supplied. */
		passlen = 24;
		ntpasslen = 24;
		clistr_push(cli, pword, pass, sizeof(pword), STR_TERMINATE|STR_CONVERT);
		clistr_push(cli, ntpword, ntpass, sizeof(ntpword), STR_TERMINATE|STR_CONVERT);
		SMBencrypt((uchar *)pword,cli->cryptkey,(uchar *)pword);
		SMBNTencrypt((uchar *)ntpword,cli->cryptkey,(uchar *)ntpword);
	} else {
		memcpy(pword, pass, passlen);
		memcpy(ntpword, ntpass, ntpasslen);
	}

	/* send a session setup command */
	memset(cli->outbuf,'\0',smb_size);

	set_message(cli->outbuf,13,0,True);
	SCVAL(cli->outbuf,smb_com,SMBsesssetupX);
	cli_setup_packet(cli);
			
	SCVAL(cli->outbuf,smb_vwv0,0xFF);
	SSVAL(cli->outbuf,smb_vwv2,CLI_BUFFER_SIZE);
	SSVAL(cli->outbuf,smb_vwv3,2);
	SSVAL(cli->outbuf,smb_vwv4,cli->pid);
	SIVAL(cli->outbuf,smb_vwv5,cli->sesskey);
	SSVAL(cli->outbuf,smb_vwv7,passlen);
	SSVAL(cli->outbuf,smb_vwv8,ntpasslen);
	SIVAL(cli->outbuf,smb_vwv11,capabilities); 
	p = smb_buf(cli->outbuf);
	memcpy(p,pword,passlen); p += passlen;
	memcpy(p,ntpword,ntpasslen); p += ntpasslen;
	p += clistr_push(cli, p, user, -1, STR_TERMINATE|STR_UPPER|STR_CONVERT);
	p += clistr_push(cli, p, workgroup, -1, STR_TERMINATE|STR_UPPER|STR_CONVERT);
	p += clistr_push(cli, p, "Unix", -1, STR_TERMINATE|STR_CONVERT);
	p += clistr_push(cli, p, "Samba", -1, STR_TERMINATE|STR_CONVERT);
	cli_setup_bcc(cli, p);

	cli_send_smb(cli);
	if (!cli_receive_smb(cli))
		return False;

	show_msg(cli->inbuf);

	if (cli_is_error(cli)) {
		return False;
	}
	
	/* use the returned vuid from now on */
	cli->vuid = SVAL(cli->inbuf,smb_uid);
	
	p = smb_buf(cli->inbuf);
	p += clistr_pull(cli, cli->server_os, p, sizeof(fstring), -1, STR_TERMINATE);
	p += clistr_pull(cli, cli->server_type, p, sizeof(fstring), -1, STR_TERMINATE);
	p += clistr_pull(cli, cli->server_domain, p, sizeof(fstring), -1, STR_TERMINATE);

	fstrcpy(cli->user_name, user);

	return True;
}
예제 #14
0
파일: ntlmssp.c 프로젝트: shihyu/r6300v2
static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, 
					 const DATA_BLOB reply, DATA_BLOB *next_request) 
{
	uint32 chal_flags, ntlmssp_command, unkn1, unkn2;
	DATA_BLOB server_domain_blob;
	DATA_BLOB challenge_blob;
	DATA_BLOB struct_blob = data_blob(NULL, 0);
	char *server_domain;
	const char *chal_parse_string;
	const char *auth_gen_string;
	DATA_BLOB lm_response = data_blob(NULL, 0);
	DATA_BLOB nt_response = data_blob(NULL, 0);
	DATA_BLOB session_key = data_blob(NULL, 0);
	DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
	NTSTATUS nt_status;

	if (!msrpc_parse(&reply, "CdBd",
			 "NTLMSSP",
			 &ntlmssp_command, 
			 &server_domain_blob,
			 &chal_flags)) {
		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#1)\n"));
		dump_data(2, (const char *)reply.data, reply.length);

		return NT_STATUS_INVALID_PARAMETER;
	}
	
	data_blob_free(&server_domain_blob);

	DEBUG(3, ("Got challenge flags:\n"));
	debug_ntlmssp_flags(chal_flags);

	ntlmssp_handle_neg_flags(ntlmssp_state, chal_flags, lp_client_lanman_auth());

	if (ntlmssp_state->unicode) {
		if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
			chal_parse_string = "CdUdbddB";
		} else {
			chal_parse_string = "CdUdbdd";
		}
		auth_gen_string = "CdBBUUUBd";
	} else {
		if (chal_flags & NTLMSSP_CHAL_TARGET_INFO) {
			chal_parse_string = "CdAdbddB";
		} else {
			chal_parse_string = "CdAdbdd";
		}

		auth_gen_string = "CdBBAAABd";
	}

	DEBUG(3, ("NTLMSSP: Set final flags:\n"));
	debug_ntlmssp_flags(ntlmssp_state->neg_flags);

	if (!msrpc_parse(&reply, chal_parse_string,
			 "NTLMSSP",
			 &ntlmssp_command, 
			 &server_domain,
			 &chal_flags,
			 &challenge_blob, 8,
			 &unkn1, &unkn2,
			 &struct_blob)) {
		DEBUG(1, ("Failed to parse the NTLMSSP Challenge: (#2)\n"));
		dump_data(2, (const char *)reply.data, reply.length);
		return NT_STATUS_INVALID_PARAMETER;
	}

	ntlmssp_state->server_domain = talloc_strdup(ntlmssp_state->mem_ctx,
						     server_domain);

	SAFE_FREE(server_domain);
	if (challenge_blob.length != 8) {
		data_blob_free(&struct_blob);
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!ntlmssp_state->password) {
		static const uchar zeros[16];
		/* do nothing - blobs are zero length */

		/* session key is all zeros */
		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, zeros, 16);
		
		/* not doing NLTM2 without a password */
		ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2;
	} else if (ntlmssp_state->use_ntlmv2) {

		if (!struct_blob.length) {
			/* be lazy, match win2k - we can't do NTLMv2 without it */
			DEBUG(1, ("Server did not provide 'target information', required for NTLMv2\n"));
			return NT_STATUS_INVALID_PARAMETER;
		}

		/* TODO: if the remote server is standalone, then we should replace 'domain'
		   with the server name as supplied above */
		
		if (!SMBNTLMv2encrypt(ntlmssp_state->user, 
				      ntlmssp_state->domain, 
				      ntlmssp_state->password, &challenge_blob, 
				      &struct_blob, 
				      &lm_response, &nt_response, &session_key)) {
			data_blob_free(&challenge_blob);
			data_blob_free(&struct_blob);
			return NT_STATUS_NO_MEMORY;
		}
	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
		struct MD5Context md5_session_nonce_ctx;
		uchar nt_hash[16];
		uchar session_nonce[16];
		uchar session_nonce_hash[16];
		uchar user_session_key[16];
		E_md4hash(ntlmssp_state->password, nt_hash);
		
		lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
		generate_random_buffer(lm_response.data, 8);
		memset(lm_response.data+8, 0, 16);

		memcpy(session_nonce, challenge_blob.data, 8);
		memcpy(&session_nonce[8], lm_response.data, 8);
	
		MD5Init(&md5_session_nonce_ctx);
		MD5Update(&md5_session_nonce_ctx, challenge_blob.data, 8);
		MD5Update(&md5_session_nonce_ctx, lm_response.data, 8);
		MD5Final(session_nonce_hash, &md5_session_nonce_ctx);

		DEBUG(5, ("NTLMSSP challenge set by NTLM2\n"));
		DEBUG(5, ("challenge is: \n"));
		dump_data(5, (const char *)session_nonce_hash, 8);
		
		nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
		SMBNTencrypt(ntlmssp_state->password,
			     session_nonce_hash,
			     nt_response.data);

		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);

		SMBsesskeygen_ntv1(nt_hash, NULL, user_session_key);
		hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data);
		dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
	} else {
		
		
		uchar lm_hash[16];
		uchar nt_hash[16];
		E_deshash(ntlmssp_state->password, lm_hash);
		E_md4hash(ntlmssp_state->password, nt_hash);
		
		/* lanman auth is insecure, it may be disabled */
		if (lp_client_lanman_auth()) {
			lm_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
			SMBencrypt(ntlmssp_state->password,challenge_blob.data,
				   lm_response.data);
		}
		
		nt_response = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 24);
		SMBNTencrypt(ntlmssp_state->password,challenge_blob.data,
			     nt_response.data);
		
		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
		if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) 
		    && lp_client_lanman_auth()) {
			SMBsesskeygen_lmv1(lm_hash, lm_response.data, 
					   session_key.data);
			dump_data_pw("LM session key\n", session_key.data, session_key.length);
		} else {
			SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data);
			dump_data_pw("NT session key:\n", session_key.data, session_key.length);
		}
	}
	data_blob_free(&struct_blob);

	/* Key exchange encryptes a new client-generated session key with
	   the password-derived key */
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
		/* Make up a new session key */
		uint8 client_session_key[16];
		generate_random_buffer(client_session_key, sizeof(client_session_key));

		/* Encrypt the new session key with the old one */
		encrypted_session_key = data_blob(client_session_key, sizeof(client_session_key));
		dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, encrypted_session_key.length);
		SamOEMhash(encrypted_session_key.data, session_key.data, encrypted_session_key.length);
		dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);

		/* Mark the new session key as the 'real' session key */
		data_blob_free(&session_key);
		session_key = data_blob_talloc(ntlmssp_state->mem_ctx, client_session_key, sizeof(client_session_key));
	}

	/* this generates the actual auth packet */
	if (!msrpc_gen(next_request, auth_gen_string, 
		       "NTLMSSP", 
		       NTLMSSP_AUTH, 
		       lm_response.data, lm_response.length,
		       nt_response.data, nt_response.length,
		       ntlmssp_state->domain, 
		       ntlmssp_state->user, 
		       ntlmssp_state->get_global_myname(), 
		       encrypted_session_key.data, encrypted_session_key.length,
		       ntlmssp_state->neg_flags)) {
		
		return NT_STATUS_NO_MEMORY;
	}

	data_blob_free(&encrypted_session_key);

	data_blob_free(&ntlmssp_state->chal);

	ntlmssp_state->chal = challenge_blob;
	ntlmssp_state->lm_resp = lm_response;
	ntlmssp_state->nt_resp = nt_response;
	ntlmssp_state->session_key = session_key;

	ntlmssp_state->expected_state = NTLMSSP_UNKNOWN;

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) {
		DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status)));
		return nt_status;
	}

	return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
				   TALLOC_CTX *mem_ctx,
				   uint32 logon_parameters,
				   const char *domain,
				   const char *username,
				   const char *password,
				   const char *workstation,
				   uint16_t validation_level,
				   int logon_type)
{
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS status;
	struct netr_Authenticator clnt_creds;
	struct netr_Authenticator ret_creds;
	union netr_LogonLevel *logon;
	union netr_Validation validation;
	uint8_t authoritative;
	fstring clnt_name_slash;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	ZERO_STRUCT(ret_creds);

	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
	if (!logon) {
		return NT_STATUS_NO_MEMORY;
	}

	if (workstation) {
		fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
	} else {
		fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
	}

	/* Initialise input parameters */

	netlogon_creds_client_authenticator(cli->dc, &clnt_creds);

	switch (logon_type) {
	case NetlogonInteractiveInformation: {

		struct netr_PasswordInfo *password_info;

		struct samr_Password lmpassword;
		struct samr_Password ntpassword;

		password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
		if (!password_info) {
			return NT_STATUS_NO_MEMORY;
		}

		nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);

		if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
			netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16);
			netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16);
		} else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
			netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
			netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
		} else {
			netlogon_creds_des_encrypt(cli->dc, &lmpassword);
			netlogon_creds_des_encrypt(cli->dc, &ntpassword);
		}

		password_info->identity_info.domain_name.string		= domain;
		password_info->identity_info.parameter_control		= logon_parameters;
		password_info->identity_info.logon_id_low		= 0xdead;
		password_info->identity_info.logon_id_high		= 0xbeef;
		password_info->identity_info.account_name.string	= username;
		password_info->identity_info.workstation.string		= clnt_name_slash;

		password_info->lmpassword = lmpassword;
		password_info->ntpassword = ntpassword;

		logon->password = password_info;

		break;
	}
	case NetlogonNetworkInformation: {
		struct netr_NetworkInfo *network_info;
		uint8 chal[8];
		unsigned char local_lm_response[24];
		unsigned char local_nt_response[24];
		struct netr_ChallengeResponse lm;
		struct netr_ChallengeResponse nt;

		ZERO_STRUCT(lm);
		ZERO_STRUCT(nt);

		network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
		if (!network_info) {
			return NT_STATUS_NO_MEMORY;
		}

		generate_random_buffer(chal, 8);

		SMBencrypt(password, chal, local_lm_response);
		SMBNTencrypt(password, chal, local_nt_response);

		lm.length = 24;
		lm.data = local_lm_response;

		nt.length = 24;
		nt.data = local_nt_response;

		network_info->identity_info.domain_name.string		= domain;
		network_info->identity_info.parameter_control		= logon_parameters;
		network_info->identity_info.logon_id_low		= 0xdead;
		network_info->identity_info.logon_id_high		= 0xbeef;
		network_info->identity_info.account_name.string		= username;
		network_info->identity_info.workstation.string		= clnt_name_slash;

		memcpy(network_info->challenge, chal, 8);
		network_info->nt = nt;
		network_info->lm = lm;

		logon->network = network_info;

		break;
	}
	default:
		DEBUG(0, ("switch value %d not supported\n",
			logon_type));
		return NT_STATUS_INVALID_INFO_CLASS;
	}

	status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
					   cli->srv_name_slash,
					   lp_netbios_name(),
					   &clnt_creds,
					   &ret_creds,
					   logon_type,
					   logon,
					   validation_level,
					   &validation,
					   &authoritative,
					   &result);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Always check returned credentials */
	if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
		DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	return result;
}
예제 #16
0
static bool wbinfo_auth_crap(char *username, const char *pass)
{
	wbcErr wbc_status = WBC_ERR_UNKNOWN_FAILURE;
	struct wbcAuthUserParams params;
	struct wbcAuthUserInfo *info = NULL;
	struct wbcAuthErrorInfo *err = NULL;
	DATA_BLOB lm = data_blob_null;
	DATA_BLOB nt = data_blob_null;
	fstring name_user;
	fstring name_domain;

	parse_wbinfo_domain_user(username, name_domain, name_user);

	params.account_name	= name_user;
	params.domain_name	= name_domain;
	params.workstation_name	= NULL;

	params.flags		= 0;
	params.parameter_control= WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
				  WBC_MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT;

	params.level		= WBC_AUTH_USER_LEVEL_RESPONSE;

	generate_random_buffer(params.password.response.challenge, 8);

	if (lp_client_ntlmv2_auth()) {
		DATA_BLOB server_chal;
		DATA_BLOB names_blob;

		server_chal = data_blob(params.password.response.challenge, 8);

		/* Pretend this is a login to 'us', for blob purposes */
		names_blob = NTLMv2_generate_names_blob(global_myname(), lp_workgroup());

		if (!SMBNTLMv2encrypt(name_user, name_domain, pass, &server_chal,
				      &names_blob,
				      &lm, &nt, NULL)) {
			data_blob_free(&names_blob);
			data_blob_free(&server_chal);
			return false;
		}
		data_blob_free(&names_blob);
		data_blob_free(&server_chal);

	} else {
		if (lp_client_lanman_auth()) {
			bool ok;
			lm = data_blob(NULL, 24);
			ok = SMBencrypt(pass, params.password.response.challenge,
					lm.data);
			if (!ok) {
				data_blob_free(&lm);
			}
		}
		nt = data_blob(NULL, 24);
		SMBNTencrypt(pass, params.password.response.challenge,
			     nt.data);
	}

	params.password.response.nt_length	= nt.length;
	params.password.response.nt_data	= nt.data;
	params.password.response.lm_length	= lm.length;
	params.password.response.lm_data	= lm.data;

	wbc_status = wbcAuthenticateUserEx(&params, &info, &err);

	/* Display response */

	d_printf("challenge/response password authentication %s\n",
		 WBC_ERROR_IS_OK(wbc_status) ? "succeeded" : "failed");

	if (wbc_status == WBC_ERR_AUTH_ERROR) {
		d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
			 err->nt_string,
			 err->nt_status,
			 err->display_string);
		wbcFreeMemory(err);
	} else if (WBC_ERROR_IS_OK(wbc_status)) {
		wbcFreeMemory(info);
	}

	data_blob_free(&nt);
	data_blob_free(&lm);

	return WBC_ERROR_IS_OK(wbc_status);
}
예제 #17
0
NTSTATUS rpccli_netlogon_password_logon(
	struct netlogon_creds_cli_context *creds_ctx,
	struct dcerpc_binding_handle *binding_handle,
	TALLOC_CTX *mem_ctx,
	uint32_t logon_parameters,
	const char *domain,
	const char *username,
	const char *password,
	const char *workstation,
	enum netr_LogonInfoClass logon_type,
	uint8_t *authoritative,
	uint32_t *flags,
	uint16_t *_validation_level,
	union netr_Validation **_validation)
{
	TALLOC_CTX *frame = talloc_stackframe();
	NTSTATUS status;
	union netr_LogonLevel *logon;
	uint16_t validation_level = 0;
	union netr_Validation *validation = NULL;
	char *workstation_slash = NULL;

	logon = talloc_zero(frame, union netr_LogonLevel);
	if (logon == NULL) {
		TALLOC_FREE(frame);
		return NT_STATUS_NO_MEMORY;
	}

	if (workstation == NULL) {
		workstation = lp_netbios_name();
	}

	workstation_slash = talloc_asprintf(frame, "\\\\%s", workstation);
	if (workstation_slash == NULL) {
		TALLOC_FREE(frame);
		return NT_STATUS_NO_MEMORY;
	}

	/* Initialise input parameters */

	switch (logon_type) {
	case NetlogonInteractiveInformation:
	case NetlogonInteractiveTransitiveInformation: {

		struct netr_PasswordInfo *password_info;

		struct samr_Password lmpassword;
		struct samr_Password ntpassword;

		password_info = talloc_zero(frame, struct netr_PasswordInfo);
		if (password_info == NULL) {
			TALLOC_FREE(frame);
			return NT_STATUS_NO_MEMORY;
		}

		nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);

		password_info->identity_info.domain_name.string		= domain;
		password_info->identity_info.parameter_control		= logon_parameters;
		password_info->identity_info.logon_id_low		= 0xdead;
		password_info->identity_info.logon_id_high		= 0xbeef;
		password_info->identity_info.account_name.string	= username;
		password_info->identity_info.workstation.string		= workstation_slash;

		password_info->lmpassword = lmpassword;
		password_info->ntpassword = ntpassword;

		logon->password = password_info;

		break;
	}
	case NetlogonNetworkInformation:
	case NetlogonNetworkTransitiveInformation: {
		struct netr_NetworkInfo *network_info;
		uint8_t chal[8];
		unsigned char local_lm_response[24];
		unsigned char local_nt_response[24];
		struct netr_ChallengeResponse lm;
		struct netr_ChallengeResponse nt;

		ZERO_STRUCT(lm);
		ZERO_STRUCT(nt);

		network_info = talloc_zero(frame, struct netr_NetworkInfo);
		if (network_info == NULL) {
			TALLOC_FREE(frame);
			return NT_STATUS_NO_MEMORY;
		}

		generate_random_buffer(chal, 8);

		SMBencrypt(password, chal, local_lm_response);
		SMBNTencrypt(password, chal, local_nt_response);

		lm.length = 24;
		lm.data = local_lm_response;

		nt.length = 24;
		nt.data = local_nt_response;

		network_info->identity_info.domain_name.string		= domain;
		network_info->identity_info.parameter_control		= logon_parameters;
		network_info->identity_info.logon_id_low		= 0xdead;
		network_info->identity_info.logon_id_high		= 0xbeef;
		network_info->identity_info.account_name.string		= username;
		network_info->identity_info.workstation.string		= workstation_slash;

		memcpy(network_info->challenge, chal, 8);
		network_info->nt = nt;
		network_info->lm = lm;

		logon->network = network_info;

		break;
	}
	default:
		DEBUG(0, ("switch value %d not supported\n",
			logon_type));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_INFO_CLASS;
	}

	status = netlogon_creds_cli_LogonSamLogon(creds_ctx,
						  binding_handle,
						  logon_type,
						  logon,
						  mem_ctx,
						  &validation_level,
						  &validation,
						  authoritative,
						  flags);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(frame);
		return status;
	}

	TALLOC_FREE(frame);
	*_validation_level = validation_level;
	*_validation = validation;

	return NT_STATUS_OK;
}