Imported Upstream version 4.6.2
This commit is contained in:
288
daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c
Normal file
288
daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c
Normal file
@@ -0,0 +1,288 @@
|
||||
/** BEGIN COPYRIGHT BLOCK
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional permission under GPLv3 section 7:
|
||||
*
|
||||
* In the following paragraph, "GPL" means the GNU General Public
|
||||
* License, version 3 or any later version, and "Non-GPL Code" means
|
||||
* code that is governed neither by the GPL nor a license
|
||||
* compatible with the GPL.
|
||||
*
|
||||
* You may link the code of this Program with Non-GPL Code and convey
|
||||
* linked combinations including the two, provided that such Non-GPL
|
||||
* Code only links to the code of this Program through those well
|
||||
* defined interfaces identified in the file named EXCEPTION found in
|
||||
* the source code files (the "Approved Interfaces"). The files of
|
||||
* Non-GPL Code may instantiate templates or use macros or inline
|
||||
* functions from the Approved Interfaces without causing the resulting
|
||||
* work to be covered by the GPL. Only the copyright holders of this
|
||||
* Program may make changes or additions to the list of Approved
|
||||
* Interfaces.
|
||||
*
|
||||
* Authors:
|
||||
* Simo Sorce <ssorce@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2007-2010 Red Hat, Inc.
|
||||
* All rights reserved.
|
||||
* END COPYRIGHT BLOCK **/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <dirsrv/slapi-plugin.h>
|
||||
#include <lber.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <endian.h>
|
||||
|
||||
#include "ipapwd.h"
|
||||
#include "util.h"
|
||||
#include "ipa_krb5.h"
|
||||
|
||||
/* krbTicketFlags */
|
||||
#define KTF_DISALLOW_POSTDATED 0x00000001
|
||||
#define KTF_DISALLOW_FORWARDABLE 0x00000002
|
||||
#define KTF_DISALLOW_TGT_BASED 0x00000004
|
||||
#define KTF_DISALLOW_RENEWABLE 0x00000008
|
||||
#define KTF_DISALLOW_PROXIABLE 0x00000010
|
||||
#define KTF_DISALLOW_DUP_SKEY 0x00000020
|
||||
#define KTF_DISALLOW_ALL_TIX 0x00000040
|
||||
#define KTF_REQUIRES_PRE_AUTH 0x00000080
|
||||
#define KTF_REQUIRES_HW_AUTH 0x00000100
|
||||
#define KTF_REQUIRES_PWCHANGE 0x00000200
|
||||
#define KTF_DISALLOW_SVR 0x00001000
|
||||
#define KTF_PWCHANGE_SERVICE 0x00002000
|
||||
|
||||
/* ascii hex output of bytes in "in"
|
||||
* out len is 32 (preallocated)
|
||||
* in len is 16 */
|
||||
static const char hexchars[] = "0123456789ABCDEF";
|
||||
static void hexbuf(char *out, const uint8_t *in)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
out[i*2] = hexchars[in[i] >> 4];
|
||||
out[i*2+1] = hexchars[in[i] & 0x0f];
|
||||
}
|
||||
}
|
||||
|
||||
void ipapwd_keyset_free(struct ipapwd_keyset **pkset)
|
||||
{
|
||||
struct ipapwd_keyset *kset = *pkset;
|
||||
int i;
|
||||
|
||||
if (!kset) return;
|
||||
|
||||
for (i = 0; i < kset->num_keys; i++) {
|
||||
free(kset->keys[i].key_data_contents[0]);
|
||||
free(kset->keys[i].key_data_contents[1]);
|
||||
}
|
||||
free(kset->keys);
|
||||
free(kset);
|
||||
*pkset = NULL;
|
||||
}
|
||||
|
||||
Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_data *data,
|
||||
char *preferred_principal,
|
||||
int num_encsalts,
|
||||
krb5_key_salt_tuple *encsalts,
|
||||
char **errMesg)
|
||||
{
|
||||
krb5_context krbctx;
|
||||
char *krbPrincipalName = NULL;
|
||||
int kvno;
|
||||
struct berval *bval = NULL;
|
||||
Slapi_Value **svals = NULL;
|
||||
krb5_principal princ = NULL;
|
||||
krb5_error_code krberr;
|
||||
krb5_data pwd = { 0 };
|
||||
struct ipapwd_keyset *kset = NULL;
|
||||
|
||||
krbctx = krbcfg->krbctx;
|
||||
|
||||
svals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *));
|
||||
if (!svals) {
|
||||
LOG_OOM();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kvno = ipapwd_get_cur_kvno(data->target);
|
||||
|
||||
if (preferred_principal) {
|
||||
krbPrincipalName = slapi_ch_strdup(preferred_principal);
|
||||
} else {
|
||||
krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
|
||||
"krbCanonicalName");
|
||||
if (!krbPrincipalName) {
|
||||
krbPrincipalName = slapi_entry_attr_get_charptr(data->target,
|
||||
"krbPrincipalName");
|
||||
}
|
||||
if (!krbPrincipalName) {
|
||||
*errMesg = "no krbPrincipalName present in this entry\n";
|
||||
LOG_FATAL("%s", *errMesg);
|
||||
goto enc_error;
|
||||
}
|
||||
}
|
||||
|
||||
krberr = krb5_parse_name(krbctx, krbPrincipalName, &princ);
|
||||
if (krberr) {
|
||||
LOG_FATAL("krb5_parse_name failed [%s]\n",
|
||||
krb5_get_error_message(krbctx, krberr));
|
||||
goto enc_error;
|
||||
}
|
||||
|
||||
if (data->password) {
|
||||
pwd.data = (char *)data->password;
|
||||
pwd.length = strlen(data->password);
|
||||
}
|
||||
|
||||
kset = (struct ipapwd_keyset *) calloc(1, sizeof(struct ipapwd_keyset));
|
||||
if (!kset) {
|
||||
LOG_OOM();
|
||||
goto enc_error;
|
||||
}
|
||||
|
||||
/* this encoding assumes all keys have the same kvno */
|
||||
/* major-vno = 1 and minor-vno = 1 */
|
||||
kset->major_vno = 1;
|
||||
kset->minor_vno = 1;
|
||||
/* increment kvno (will be 1 if this is a new entry) */
|
||||
kvno += 1;
|
||||
kset->mkvno = krbcfg->mkvno;
|
||||
|
||||
krberr = ipa_krb5_generate_key_data(krbctx, princ,
|
||||
pwd, kvno, krbcfg->kmkey,
|
||||
num_encsalts, encsalts,
|
||||
&kset->num_keys, &kset->keys);
|
||||
if (krberr != 0) {
|
||||
LOG_FATAL("generating kerberos keys failed [%s]\n",
|
||||
krb5_get_error_message(krbctx, krberr));
|
||||
goto enc_error;
|
||||
}
|
||||
|
||||
krberr = ber_encode_krb5_key_data(kset->keys, kset->num_keys,
|
||||
kset->mkvno, &bval);
|
||||
if (krberr != 0) {
|
||||
LOG_FATAL("encoding krb5_key_data failed\n");
|
||||
goto enc_error;
|
||||
}
|
||||
|
||||
svals[0] = slapi_value_new_berval(bval);
|
||||
if (!svals[0]) {
|
||||
LOG_FATAL("Converting berval to Slapi_Value\n");
|
||||
goto enc_error;
|
||||
}
|
||||
|
||||
ipapwd_keyset_free(&kset);
|
||||
krb5_free_principal(krbctx, princ);
|
||||
slapi_ch_free_string(&krbPrincipalName);
|
||||
ber_bvfree(bval);
|
||||
return svals;
|
||||
|
||||
enc_error:
|
||||
*errMesg = "key encryption/encoding failed\n";
|
||||
if (kset) ipapwd_keyset_free(&kset);
|
||||
krb5_free_principal(krbctx, princ);
|
||||
slapi_ch_free_string(&krbPrincipalName);
|
||||
if (bval) ber_bvfree(bval);
|
||||
free(svals);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ipapwd_gen_hashes(struct ipapwd_krbcfg *krbcfg,
|
||||
struct ipapwd_data *data, char *userpw,
|
||||
int is_krb, int is_smb, int is_ipant, Slapi_Value ***svals,
|
||||
char **nthash, Slapi_Value ***ntvals,
|
||||
char **errMesg)
|
||||
{
|
||||
int rc;
|
||||
|
||||
*svals = NULL;
|
||||
*nthash = NULL;
|
||||
*errMesg = NULL;
|
||||
|
||||
if (is_krb) {
|
||||
|
||||
*svals = ipapwd_encrypt_encode_key(krbcfg, data, NULL,
|
||||
krbcfg->num_pref_encsalts,
|
||||
krbcfg->pref_encsalts,
|
||||
errMesg);
|
||||
|
||||
if (!*svals) {
|
||||
/* errMesg should have been set in encrypt_encode_key() */
|
||||
LOG_FATAL("key encryption/encoding failed\n");
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_smb || is_ipant) {
|
||||
char nt[33];
|
||||
uint8_t nt_key[16];
|
||||
int ret;
|
||||
|
||||
if (krbcfg->allow_nt_hash) {
|
||||
ret = encode_nt_key(userpw, nt_key);
|
||||
if (ret) {
|
||||
*errMesg = "Failed to generate NT/LM hashes\n";
|
||||
LOG_FATAL("%s", *errMesg);
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
hexbuf(nt, nt_key);
|
||||
nt[32] = '\0';
|
||||
*nthash = slapi_ch_strdup(nt);
|
||||
} else {
|
||||
memset(nt_key, 0, 16);
|
||||
}
|
||||
|
||||
if (is_ipant) {
|
||||
*ntvals = (Slapi_Value **)calloc(2, sizeof(Slapi_Value *));
|
||||
if (!*ntvals) {
|
||||
LOG_OOM();
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
(*ntvals)[0] = slapi_value_new();
|
||||
if (slapi_value_set((*ntvals)[0], nt_key, 16) == NULL) {
|
||||
rc = LDAP_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = LDAP_SUCCESS;
|
||||
|
||||
done:
|
||||
|
||||
/* when error, free possibly allocated output parameters */
|
||||
if (rc) {
|
||||
ipapwd_free_slapi_value_array(svals);
|
||||
ipapwd_free_slapi_value_array(ntvals);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user