/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#include <locale.h>
#include <errno.h>
#include <unistd.h>
#include <ctype.h>
#include <syslog.h>
#include <sys/time.h>
#include "ns_sldap.h"
#include "ns_internal.h"
#include <crypt.h>
static char t1[ROTORSIZE];
static char t2[ROTORSIZE];
static char t3[ROTORSIZE];
static char hexdig[] = "0123456789abcdef";
static mutex_t ns_crypt_lock = DEFAULTMUTEX;
static boolean_t crypt_inited = B_FALSE;
static int
is_cleartext(const char *pwd)
{
if (0 == strncmp(pwd, CRYPTMARK, strlen(CRYPTMARK)))
return (FALSE);
return (TRUE);
}
static char *
hex2ascii(char *aString, int aLen)
{
char *res;
int i = 0;
if ((res = (char *)calloc(aLen*2 + 1, 1)) == NULL) {
return (NULL);
}
for (;;) {
if (aLen < 1)
break;
res[i] = hexdig[(*aString & 0xf0) >> 4];
res[i + 1] = hexdig[*aString & 0x0f];
i += 2;
aLen--;
aString++;
}
return (res);
}
static int
unhex(char c)
{
return (c >= '0' && c <= '9' ? c - '0'
: c >= 'A' && c <= 'F' ? c - 'A' + 10
: c - 'a' + 10);
}
static char *
ascii2hex(char *anHexaStr, int *aResLen)
{
int theLen = 0;
char *theRes = malloc(strlen(anHexaStr) /2 + 1);
if (theRes == NULL)
return (NULL);
while (isxdigit(*anHexaStr)) {
theRes[theLen] = unhex(*anHexaStr) << 4;
if (++anHexaStr != '\0') {
theRes[theLen] += unhex(*anHexaStr);
anHexaStr++;
}
theLen++;
}
theRes[theLen] = '\0';
*aResLen = theLen;
return (theRes);
}
static void
c_setup()
{
int ic, i, k, temp;
unsigned random;
char buf[13];
int seed;
(void) mutex_lock(&ns_crypt_lock);
if (crypt_inited) {
(void) mutex_unlock(&ns_crypt_lock);
return;
}
(void) strcpy(buf, "Homer J");
buf[8] = buf[0];
buf[9] = buf[1];
(void) strncpy(buf, (char *)crypt(buf, &buf[8]), 13);
seed = 123;
for (i = 0; i < 13; i++)
seed = seed*buf[i] + i;
for (i = 0; i < ROTORSIZE; i++) {
t1[i] = i;
t3[i] = 0;
}
for (i = 0; i < ROTORSIZE; i++) {
seed = 5*seed + buf[i%13];
random = seed % 65521;
k = ROTORSIZE-1 - i;
ic = (random&MASK)%(k+1);
random >>= 8;
temp = t1[k];
t1[k] = t1[ic];
t1[ic] = temp;
if (t3[k] != 0) continue;
ic = (random&MASK) % k;
while (t3[ic] != 0) ic = (ic + 1) % k;
t3[k] = ic;
t3[ic] = k;
}
for (i = 0; i < ROTORSIZE; i++)
t2[t1[i]&MASK] = i;
crypt_inited = B_TRUE;
(void) mutex_unlock(&ns_crypt_lock);
}
static char *
modvalue(char *str, int len, int *mod_len)
{
int i, n1, n2;
char *s;
if (!crypt_inited)
c_setup();
i = 0;
n1 = 0;
n2 = 0;
if ((s = (char *)malloc(2 * len + 1)) != NULL) {
while (i < len) {
s[i] = t2[(t3[(t1[(str[i]+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
i++;
n1++;
if (n1 == ROTORSIZE) {
n1 = 0;
n2++;
if (n2 == ROTORSIZE) n2 = 0;
}
}
s[i] = '\0';
if (mod_len != NULL)
*mod_len = i;
}
return (s);
}
char *
evalue(char *ptr)
{
char *modv, *str, *ev;
int modv_len;
size_t len;
/*
* if not cleartext, return a copy of what ptr
* points to as that is what evalue does below.
*/
if (FALSE == is_cleartext(ptr)) {
str = strdup(ptr);
return (str);
}
modv = modvalue(ptr, strlen(ptr), &modv_len);
str = hex2ascii(modv, modv_len);
free(modv);
modv = NULL;
len = strlen(str) + strlen(CRYPTMARK) + 1;
ev = malloc(len);
if (ev == NULL) {
free(str);
return (NULL);
}
(void) snprintf(ev, len, CRYPTMARK "%s", str);
free(str);
str = NULL;
return (ev);
}
char *
dvalue(char *ptr)
{
char *modv, *str, *sb;
int len;
/* if cleartext return NULL (error!) */
if (TRUE == is_cleartext(ptr))
return (NULL);
sb = strchr(ptr, '}');
sb++;
len = strlen(sb);
str = ascii2hex(sb, &len);
modv = modvalue(str, len, NULL);
free(str);
str = NULL;
return (modv);
}