ldap_service_stash.c [plain text]
#include <ctype.h>
#include "ldap_main.h"
#include "kdb_ldap.h"
#include "ldap_service_stash.h"
krb5_error_code
krb5_ldap_readpassword(context, ldap_context, password)
krb5_context context;
krb5_ldap_context *ldap_context;
unsigned char **password;
{
int entryfound=0;
krb5_error_code st=0;
char line[RECORDLEN]="0", *start=NULL, *file=NULL;
char errbuf[1024];
FILE *fptr=NULL;
*password = NULL;
if (ldap_context->service_password_file)
file = ldap_context->service_password_file;
#ifndef HAVE_STRERROR_R
# undef strerror_r
# define strerror_r(ERRNUM, BUF, SIZE) (strncpy(BUF, strerror(ERRNUM), SIZE), BUF[(SIZE)-1] = 0)
#endif
if (access(file, F_OK) < 0) {
st = errno;
strerror_r(errno, errbuf, sizeof(errbuf));
krb5_set_error_message (context, st, "%s", errbuf);
goto rp_exit;
}
if (access(file, R_OK) < 0) {
st = errno;
strerror_r(errno, errbuf, sizeof(errbuf));
krb5_set_error_message (context, st, "%s", errbuf);
goto rp_exit;
}
if ((fptr=fopen(file, "r")) == NULL) {
st = errno;
strerror_r(errno, errbuf, sizeof(errbuf));
krb5_set_error_message (context, st, "%s", errbuf);
goto rp_exit;
}
while (fgets(line, RECORDLEN, fptr)!= NULL) {
char tmp[RECORDLEN];
tmp[0] = '\0';
for (start = line; isspace(*start); ++start);
if (*start == '!' || *start == '#')
continue;
sscanf(line, "%*[ \t]%[^#]", tmp);
if (tmp[0] == '\0')
sscanf(line, "%[^#]", tmp);
if (strcasecmp(tmp, ldap_context->bind_dn) == 0) {
entryfound = 1;
break;
}
}
fclose (fptr);
if (entryfound == 0) {
st = KRB5_KDB_SERVER_INTERNAL_ERR;
krb5_set_error_message (context, st, "Bind DN entry missing in stash file");
goto rp_exit;
}
start = strchr(line, '\n');
if (start)
*start = '\0';
start = strchr(line, '#');
if (start == NULL) {
st = KRB5_KDB_SERVER_INTERNAL_ERR;
krb5_set_error_message (context, st, "Stash file entry corrupt");
goto rp_exit;
}
++ start;
{
struct data PT, CT;
if (!strncmp(start, "{FILE}", strlen("{FILE}"))) {
*password = (unsigned char *)malloc(strlen(start) + 2);
if (*password == NULL) {
st = ENOMEM;
goto rp_exit;
}
(*password)[strlen(start) + 1] = '\0';
(*password)[strlen(start)] = '\0';
strcpy((char *)(*password), start);
goto got_password;
} else {
CT.value = (unsigned char *)start;
CT.len = strlen((char *)CT.value);
st = dec_password(CT, &PT);
if (st != 0) {
switch (st) {
case ERR_NO_MEM:
st = ENOMEM;
break;
case ERR_PWD_ZERO:
st = EINVAL;
krb5_set_error_message(context, st, "Password has zero length");
break;
case ERR_PWD_BAD:
st = EINVAL;
krb5_set_error_message(context, st, "Password corrupted");
break;
case ERR_PWD_NOT_HEX:
st = EINVAL;
krb5_set_error_message(context, st, "Not a hexadecimal password");
break;
default:
st = KRB5_KDB_SERVER_INTERNAL_ERR;
break;
}
goto rp_exit;
}
*password = PT.value;
}
}
got_password:
rp_exit:
if (st) {
if (*password)
free (*password);
*password = NULL;
}
return st;
}
int
tohex(in, ret)
krb5_data in;
krb5_data *ret;
{
int i=0, err = 0;
ret->length = 0;
ret->data = NULL;
ret->data = malloc((unsigned int)in.length * 2 + 1 );
if (ret->data == NULL) {
err = ENOMEM;
goto cleanup;
}
ret->length = in.length * 2;
ret->data[ret->length] = 0;
for (i = 0; i < in.length; i++)
sprintf(ret->data + 2 * i, "%02x", in.data[i] & 0xff);
cleanup:
if (ret->length == 0) {
free(ret->data);
ret->data = NULL;
}
return err;
}
int dec_password(struct data pwd, struct data *ret) {
int err=0;
int i=0, j=0;
ret->len = 0;
ret->value = NULL;
if (pwd.len == 0) {
err = ERR_PWD_ZERO;
ret->len = 0;
goto cleanup;
}
if (pwd.len >= strlen("{HEX}") &&
strncmp((char *)pwd.value, "{HEX}", strlen("{HEX}")) == 0) {
if ((pwd.len - strlen("{HEX}")) % 2 != 0) {
err = ERR_PWD_BAD;
ret->len = 0;
goto cleanup;
}
ret->value = (unsigned char *)malloc((pwd.len - strlen("{HEX}")) / 2 + 1);
if (ret->value == NULL) {
err = ERR_NO_MEM;
ret->len = 0;
goto cleanup;
}
ret->len = (pwd.len - strlen("{HEX}")) / 2;
ret->value[ret->len] = '\0';
for (i = strlen("{HEX}"), j = 0; i < pwd.len; i += 2, j++) {
unsigned int k;
if (isxdigit(pwd.value[i]) == 0 || isxdigit(pwd.value[i + 1]) == 0) {
err = ERR_PWD_NOT_HEX;
ret->len = 0;
goto cleanup;
}
sscanf((char *)pwd.value + i, "%2x", &k);
ret->value[j] = k;
}
goto cleanup;
} else {
err = ERR_PWD_NOT_HEX;
ret->len = 0;
goto cleanup;
}
cleanup:
if (ret->len == 0) {
free(ret->value);
ret->value = NULL;
}
return(err);
}