示例#1
0
BOOL check_lanman_password(char *user, uchar *pass1, 
                           uchar *pass2, struct smb_passwd **psmbpw)
{
  static uchar null_pw[16];
  uchar unenc_new_pw[16];
  uchar unenc_old_pw[16];
  struct smb_passwd *smbpw;

  *psmbpw = NULL;

  become_root(0);
  smbpw = getsmbpwnam(user);
  unbecome_root(0);

  if (smbpw == NULL)
  {
    DEBUG(0,("check_lanman_password: getsmbpwnam returned NULL\n"));
    return False;
  }

  if (smbpw->acct_ctrl & ACB_DISABLED)
  {
    DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
    return False;
  }

  if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
  {
    uchar no_pw[14];
    memset(no_pw, '\0', 14);
    E_P16(no_pw, null_pw);
    smbpw->smb_passwd = null_pw;
  } else if (smbpw->smb_passwd == NULL) {
    DEBUG(0,("check_lanman_password: no lanman password !\n"));
    return False;
  }

  /* Get the new lanman hash. */
  D_P16(smbpw->smb_passwd, pass2, unenc_new_pw);

  /* Use this to get the old lanman hash. */
  D_P16(unenc_new_pw, pass1, unenc_old_pw);

  /* Check that the two old passwords match. */
  if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
  {
    DEBUG(0,("check_lanman_password: old password doesn't match.\n"));
    return False;
  }

  *psmbpw = smbpw;
  return True;
}
示例#2
0
BOOL change_lanman_password(struct smb_passwd *smbpw, uchar *pass1, uchar *pass2)
{
  static uchar null_pw[16];
  uchar unenc_new_pw[16];
  BOOL ret;

  if (smbpw == NULL)
  { 
    DEBUG(0,("change_lanman_password: no smb password entry.\n"));
    return False;
  }

  if (smbpw->acct_ctrl & ACB_DISABLED)
  {
    DEBUG(0,("change_lanman_password: account %s disabled.\n", smbpw->smb_name));
    return False;
  }

  if ((smbpw->smb_passwd == NULL) && (smbpw->acct_ctrl & ACB_PWNOTREQ))
  {
    uchar no_pw[14];
    memset(no_pw, '\0', 14);
    E_P16(no_pw, null_pw);
    smbpw->smb_passwd = null_pw;
  } else if (smbpw->smb_passwd == NULL) {
    DEBUG(0,("change_lanman_password: no lanman password !\n"));
    return False;
  }

  /* Get the new lanman hash. */
  D_P16(smbpw->smb_passwd, pass2, unenc_new_pw);

  smbpw->smb_passwd = unenc_new_pw;
  smbpw->smb_nt_passwd = NULL; /* We lose the NT hash. Sorry. */

  /* Now write it into the file. */
  become_root(0);
  ret = mod_smbpwd_entry(smbpw,False);
  unbecome_root(0);
    
  return ret;
}
示例#3
0
/***********************************************************
 Code to check the OEM hashed password.

 this function ignores the 516 byte nt OEM hashed password
 but does use the lm OEM password to check the nt hashed-hash.

************************************************************/
BOOL check_oem_password(char *user,
			uchar *lmdata, uchar *lmhash,
			uchar *ntdata, uchar *nthash,
                        struct smb_passwd **psmbpw, char *new_passwd,
                        int new_passwd_size)
{
	static uchar null_pw[16];
	static uchar null_ntpw[16];
	struct smb_passwd *smbpw = NULL;
	int new_pw_len;
	uchar new_ntp16[16];
	uchar unenc_old_ntpw[16];
	uchar new_p16[16];
	uchar unenc_old_pw[16];
	char no_pw[2];

	BOOL nt_pass_set = (ntdata != NULL && nthash != NULL);

	become_root(False);
	*psmbpw = smbpw = getsmbpwnam(user);
	unbecome_root(False);

	if (smbpw == NULL)
	{
		DEBUG(0,("check_oem_password: getsmbpwnam returned NULL\n"));
		return False;
	}

	if (smbpw->acct_ctrl & ACB_DISABLED)
	{
		DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
		return False;
	}

	/* construct a null password (in case one is needed */
	no_pw[0] = 0;
	no_pw[1] = 0;
	nt_lm_owf_gen(no_pw, null_ntpw, null_pw);

	/* check for null passwords */
	if (smbpw->smb_passwd == NULL)
	{
		if (smbpw->acct_ctrl & ACB_PWNOTREQ)
		{
			smbpw->smb_passwd = null_pw;
		}
		else 
		{
			DEBUG(0,("check_oem_password: no lanman password !\n"));
			return False;
		}
	}

	if (smbpw->smb_nt_passwd == NULL && nt_pass_set)
	{
		if (smbpw->acct_ctrl & ACB_PWNOTREQ)
		{
			smbpw->smb_nt_passwd = null_pw;
		}
		else 
		{
			DEBUG(0,("check_oem_password: no ntlm password !\n"));
			return False;
		}
	}

	/* 
	 * Call the hash function to get the new password.
	 */
	SamOEMhash( (uchar *)lmdata, (uchar *)smbpw->smb_passwd, True);

	/* 
	 * The length of the new password is in the last 4 bytes of
	 * the data buffer.
	 */

	new_pw_len = IVAL(lmdata, 512);
	if (new_pw_len < 0 || new_pw_len > new_passwd_size - 1)
	{
		DEBUG(0,("check_oem_password: incorrect password length (%d).\n", new_pw_len));
		return False;
	}

	if (nt_pass_set)
	{
		/*
		 * nt passwords are in unicode
		 */
		int uni_pw_len = new_pw_len;
		char *pw;
		new_pw_len /= 2;
		pw = dos_unistrn2((uint16*)(&lmdata[512-uni_pw_len]), new_pw_len);
		memcpy(new_passwd, pw, new_pw_len+1);
	}
	else
	{
		memcpy(new_passwd, &lmdata[512-new_pw_len], new_pw_len);
		new_passwd[new_pw_len] = '\0';
	}

	/*
	 * To ensure we got the correct new password, hash it and
	 * use it as a key to test the passed old password.
	 */

	nt_lm_owf_gen(new_passwd, new_ntp16, new_p16);

	if (!nt_pass_set)
	{
		/*
		 * Now use new_p16 as the key to see if the old
		 * password matches.
		 */
		D_P16(new_p16  , lmhash, unenc_old_pw);

		if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
		{
			DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
			return False;
		}

#ifdef DEBUG_PASSWORD
		DEBUG(100,("check_oem_password: password %s ok\n", new_passwd));
#endif
		return True;
	}

	/*
	 * Now use new_p16 as the key to see if the old
	 * password matches.
	 */
	D_P16(new_ntp16, lmhash, unenc_old_pw);
	D_P16(new_ntp16, nthash, unenc_old_ntpw);

	if (memcmp(smbpw->smb_passwd, unenc_old_pw, 16))
	{
		DEBUG(0,("check_oem_password: old lm password doesn't match.\n"));
		return False;
	}

	if (memcmp(smbpw->smb_nt_passwd, unenc_old_ntpw, 16))
	{
		DEBUG(0,("check_oem_password: old nt password doesn't match.\n"));
		return False;
	}
#ifdef DEBUG_PASSWORD
	DEBUG(100,("check_oem_password: password %s ok\n", new_passwd));
#endif
	return True;
}
示例#4
0
/*
  samr_ChangePasswordUser
*/
NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call,
					TALLOC_CTX *mem_ctx,
					struct samr_ChangePasswordUser *r)
{
	struct dcesrv_handle *h;
	struct samr_account_state *a_state;
	struct ldb_context *sam_ctx;
	struct ldb_message **res;
	int ret;
	struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
	struct samr_Password *lm_pwd, *nt_pwd;
	NTSTATUS status = NT_STATUS_OK;
	const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };

	DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);

	a_state = h->data;

	/* basic sanity checking on parameters.  Do this before any database ops */
	if (!r->in.lm_present || !r->in.nt_present ||
	    !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
	    !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
		/* we should really handle a change with lm not
		   present */
		return NT_STATUS_INVALID_PARAMETER_MIX;
	}

	/* Connect to a SAMDB with system privileges for fetching the old pw
	 * hashes. */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
				dce_call->conn->dce_ctx->lp_ctx,
				system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* fetch the old hashes */
	ret = gendb_search_dn(sam_ctx, mem_ctx,
			      a_state->account_dn, &res, attrs);
	if (ret != 1) {
		return NT_STATUS_WRONG_PASSWORD;
	}

	status = samdb_result_passwords(mem_ctx,
					dce_call->conn->dce_ctx->lp_ctx,
					res[0], &lm_pwd, &nt_pwd);
	if (!NT_STATUS_IS_OK(status) || !nt_pwd) {
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* decrypt and check the new lm hash */
	if (lm_pwd) {
		D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
		D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
		if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
			return NT_STATUS_WRONG_PASSWORD;
		}
	}

	/* decrypt and check the new nt hash */
	D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
	D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
	if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* The NT Cross is not required by Win2k3 R2, but if present
	   check the nt cross hash */
	if (r->in.cross1_present && r->in.nt_cross && lm_pwd) {
		D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
		if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
			return NT_STATUS_WRONG_PASSWORD;
		}
	}

	/* The LM Cross is not required by Win2k3 R2, but if present
	   check the lm cross hash */
	if (r->in.cross2_present && r->in.lm_cross && lm_pwd) {
		D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
		if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
			return NT_STATUS_WRONG_PASSWORD;
		}
	}

	/* Start a SAM with user privileges for the password change */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
				dce_call->conn->dce_ctx->lp_ctx,
				dce_call->conn->auth_state.session_info, 0);
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* Start transaction */
	ret = ldb_transaction_start(sam_ctx);
	if (ret != LDB_SUCCESS) {
		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	/* Performs the password modification. We pass the old hashes read out
	 * from the database since they were already checked against the user-
	 * provided ones. */
	status = samdb_set_password(sam_ctx, mem_ctx,
				    a_state->account_dn,
				    a_state->domain_state->domain_dn,
				    NULL, &new_lmPwdHash, &new_ntPwdHash,
				    lm_pwd, nt_pwd, /* this is a user password change */
				    NULL,
				    NULL);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_transaction_cancel(sam_ctx);
		return status;
	}

	/* And this confirms it in a transaction commit */
	ret = ldb_transaction_commit(sam_ctx);
	if (ret != LDB_SUCCESS) {
		DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
			 ldb_dn_get_linearized(a_state->account_dn),
			 ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	return NT_STATUS_OK;
}
示例#5
0
/* 
  samr_ChangePasswordUser 
*/
NTSTATUS dcesrv_samr_ChangePasswordUser(struct dcesrv_call_state *dce_call, 
					TALLOC_CTX *mem_ctx,
					struct samr_ChangePasswordUser *r)
{
	struct dcesrv_handle *h;
	struct samr_account_state *a_state;
	struct ldb_context *sam_ctx;
	struct ldb_message **res, *msg;
	int ret;
	struct samr_Password new_lmPwdHash, new_ntPwdHash, checkHash;
	struct samr_Password *lm_pwd, *nt_pwd;
	NTSTATUS status = NT_STATUS_OK;
	const char * const attrs[] = { "dBCSPwd", "unicodePwd" , NULL };

	DCESRV_PULL_HANDLE(h, r->in.user_handle, SAMR_HANDLE_USER);

	a_state = h->data;

	/* basic sanity checking on parameters.  Do this before any database ops */
	if (!r->in.lm_present || !r->in.nt_present ||
	    !r->in.old_lm_crypted || !r->in.new_lm_crypted ||
	    !r->in.old_nt_crypted || !r->in.new_nt_crypted) {
		/* we should really handle a change with lm not
		   present */
		return NT_STATUS_INVALID_PARAMETER_MIX;
	}

	/* To change a password we need to open as system */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	ret = ldb_transaction_start(sam_ctx);
	if (ret) {
		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	/* fetch the old hashes */
	ret = gendb_search_dn(sam_ctx, mem_ctx,
			      a_state->account_dn, &res, attrs);
	if (ret != 1) {
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_WRONG_PASSWORD;
	}
	msg = res[0];

	status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
					msg, &lm_pwd, &nt_pwd);
	if (!NT_STATUS_IS_OK(status) || !lm_pwd || !nt_pwd) {
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* decrypt and check the new lm hash */
	D_P16(lm_pwd->hash, r->in.new_lm_crypted->hash, new_lmPwdHash.hash);
	D_P16(new_lmPwdHash.hash, r->in.old_lm_crypted->hash, checkHash.hash);
	if (memcmp(checkHash.hash, lm_pwd, 16) != 0) {
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* decrypt and check the new nt hash */
	D_P16(nt_pwd->hash, r->in.new_nt_crypted->hash, new_ntPwdHash.hash);
	D_P16(new_ntPwdHash.hash, r->in.old_nt_crypted->hash, checkHash.hash);
	if (memcmp(checkHash.hash, nt_pwd, 16) != 0) {
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_WRONG_PASSWORD;
	}
	
	/* The NT Cross is not required by Win2k3 R2, but if present
	   check the nt cross hash */
	if (r->in.cross1_present && r->in.nt_cross) {
		D_P16(lm_pwd->hash, r->in.nt_cross->hash, checkHash.hash);
		if (memcmp(checkHash.hash, new_ntPwdHash.hash, 16) != 0) {
			ldb_transaction_cancel(sam_ctx);
			return NT_STATUS_WRONG_PASSWORD;
		}
	}

	/* The LM Cross is not required by Win2k3 R2, but if present
	   check the lm cross hash */
	if (r->in.cross2_present && r->in.lm_cross) {
		D_P16(nt_pwd->hash, r->in.lm_cross->hash, checkHash.hash);
		if (memcmp(checkHash.hash, new_lmPwdHash.hash, 16) != 0) {
			ldb_transaction_cancel(sam_ctx);
			return NT_STATUS_WRONG_PASSWORD;
		}
	}

	msg = ldb_msg_new(mem_ctx);
	if (msg == NULL) {
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	msg->dn = ldb_dn_copy(msg, a_state->account_dn);
	if (!msg->dn) {
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* setup password modify mods on the user DN specified.  This may fail
	 * due to password policies.  */
	status = samdb_set_password(sam_ctx, mem_ctx,
				    a_state->account_dn, a_state->domain_state->domain_dn,
				    msg, NULL, &new_lmPwdHash, &new_ntPwdHash, 
				    true, /* this is a user password change */
				    NULL,
				    NULL);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_transaction_cancel(sam_ctx);
		return status;
	}

	/* The above call only setup the modifications, this actually
	 * makes the write to the database. */
	ret = samdb_replace(sam_ctx, mem_ctx, msg);
	if (ret != 0) {
		DEBUG(2,("Failed to modify record to change password on %s: %s\n",
			 ldb_dn_get_linearized(a_state->account_dn),
			 ldb_errstring(sam_ctx)));
		ldb_transaction_cancel(sam_ctx);
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* And this confirms it in a transaction commit */
	ret = ldb_transaction_commit(sam_ctx);
	if (ret != 0) {
		DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
			 ldb_dn_get_linearized(a_state->account_dn),
			 ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	return NT_STATUS_OK;
}