1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright 1999-2003 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 #pragma ident   "%Z%%M% %I%     %E% SMI"
  31 
  32 #include <stdlib.h>
  33 #include <string.h>
  34 #include <libintl.h>
  35 #include <locale.h>
  36 #include <errno.h>
  37 #include <unistd.h>
  38 #include <ctype.h>
  39 #include <syslog.h>
  40 #include <sys/time.h>
  41 #include "ns_sldap.h"
  42 #include "ns_internal.h"
  43 #include <crypt.h>
  44 
  45 static  char            t1[ROTORSIZE];
  46 static  char            t2[ROTORSIZE];
  47 static  char            t3[ROTORSIZE];
  48 static  char            hexdig[] = "0123456789abcdef";
  49 
  50 static mutex_t          ns_crypt_lock = DEFAULTMUTEX;
  51 static boolean_t        crypt_inited = B_FALSE;
  52 
  53 static int
  54 is_cleartext(const char *pwd)
  55 {
  56         if (0 == strncmp(pwd, CRYPTMARK, strlen(CRYPTMARK)))
  57                 return (FALSE);
  58         return (TRUE);
  59 }
  60 
  61 
  62 static char *
  63 hex2ascii(char *aString, int aLen)
  64 {
  65         char *res;
  66         int i = 0;
  67 
  68         if ((res = (char *)calloc(aLen*2 + 1, 1)) == NULL) {
  69                 return (NULL);
  70         }
  71         for (;;) {
  72                 if (aLen < 1)
  73                         break;
  74                 res[i] = hexdig[(*aString & 0xf0) >> 4];
  75                 res[i + 1] = hexdig[*aString & 0x0f];
  76                 i += 2;
  77                 aLen--;
  78                 aString++;
  79         }
  80         return (res);
  81 }
  82 
  83 
  84 static int
  85 unhex(char c)
  86 {
  87         return (c >= '0' && c <= '9' ? c - '0'
  88                 : c >= 'A' && c <= 'F' ? c - 'A' + 10
  89                 : c - 'a' + 10);
  90 }
  91 
  92 
  93 static char *
  94 ascii2hex(char *anHexaStr, int *aResLen)
  95 {
  96         int theLen = 0;
  97         char *theRes = malloc(strlen(anHexaStr) /2 + 1);
  98 
  99         if (theRes == NULL)
 100                 return (NULL);
 101         while (isxdigit(*anHexaStr)) {
 102                 theRes[theLen] = unhex(*anHexaStr) << 4;
 103                 if (++anHexaStr != '\0') {
 104                         theRes[theLen] += unhex(*anHexaStr);
 105                         anHexaStr++;
 106                 }
 107                 theLen++;
 108         }
 109         theRes[theLen] = '\0';
 110         *aResLen = theLen;
 111         return (theRes);
 112 }
 113 
 114 
 115 static void
 116 c_setup()
 117 {
 118         int ic, i, k, temp;
 119         unsigned random;
 120         char buf[13];
 121         int seed;
 122 
 123         (void) mutex_lock(&ns_crypt_lock);
 124         if (crypt_inited) {
 125                 (void) mutex_unlock(&ns_crypt_lock);
 126                 return;
 127         }
 128         (void) strcpy(buf, "Homer J");
 129         buf[8] = buf[0];
 130         buf[9] = buf[1];
 131         (void) strncpy(buf, (char *)crypt(buf, &buf[8]), 13);
 132         seed = 123;
 133         for (i = 0; i < 13; i++)
 134                 seed = seed*buf[i] + i;
 135         for (i = 0; i < ROTORSIZE; i++) {
 136                 t1[i] = i;
 137                 t3[i] = 0;
 138         }
 139         for (i = 0; i < ROTORSIZE; i++) {
 140                 seed = 5*seed + buf[i%13];
 141                 random = seed % 65521;
 142                 k = ROTORSIZE-1 - i;
 143                 ic = (random&MASK)%(k+1);
 144                 random >>= 8;
 145                 temp = t1[k];
 146                 t1[k] = t1[ic];
 147                 t1[ic] = temp;
 148                 if (t3[k] != 0) continue;
 149                 ic = (random&MASK) % k;
 150                 while (t3[ic] != 0) ic = (ic + 1) % k;
 151                 t3[k] = ic;
 152                 t3[ic] = k;
 153         }
 154         for (i = 0; i < ROTORSIZE; i++)
 155                 t2[t1[i]&MASK] = i;
 156         crypt_inited = B_TRUE;
 157         (void) mutex_unlock(&ns_crypt_lock);
 158 }
 159 
 160 
 161 static char *
 162 modvalue(char *str, int len, int *mod_len)
 163 {
 164         int i, n1, n2;
 165         char *s;
 166 
 167         if (!crypt_inited)
 168                 c_setup();
 169         i = 0;
 170         n1 = 0;
 171         n2 = 0;
 172         if ((s = (char *)malloc(2 * len + 1)) != NULL) {
 173                 while (i < len) {
 174                     s[i] = t2[(t3[(t1[(str[i]+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
 175                     i++;
 176                     n1++;
 177                     if (n1 == ROTORSIZE) {
 178                         n1 = 0;
 179                         n2++;
 180                         if (n2 == ROTORSIZE) n2 = 0;
 181                     }
 182                 }
 183                 s[i] = '\0';
 184                 if (mod_len != NULL)
 185                     *mod_len = i;
 186         }
 187         return (s);
 188 }
 189 
 190 
 191 char *
 192 evalue(char *ptr)
 193 {
 194         char *modv, *str, *ev;
 195         int modv_len;
 196         size_t len;
 197 
 198         /*
 199          * if not cleartext, return a copy of what ptr
 200          * points to as that is what evalue does below.
 201          */
 202         if (FALSE == is_cleartext(ptr)) {
 203                 str = strdup(ptr);
 204                 return (str);
 205         }
 206 
 207         modv = modvalue(ptr, strlen(ptr), &modv_len);
 208         str = hex2ascii(modv, modv_len);
 209         free(modv);
 210         modv = NULL;
 211         len = strlen(str) + strlen(CRYPTMARK) + 1;
 212         ev = malloc(len);
 213         if (ev == NULL) {
 214                 free(str);
 215                 return (NULL);
 216         }
 217         (void) snprintf(ev, len, CRYPTMARK "%s", str);
 218         free(str);
 219         str = NULL;
 220         return (ev);
 221 }
 222 
 223 
 224 char *
 225 dvalue(char *ptr)
 226 {
 227         char *modv, *str, *sb;
 228         int len;
 229 
 230         /* if cleartext return NULL (error!) */
 231         if (TRUE == is_cleartext(ptr))
 232                 return (NULL);
 233 
 234         sb = strchr(ptr, '}');
 235         sb++;
 236         len = strlen(sb);
 237         str = ascii2hex(sb, &len);
 238         modv = modvalue(str, len, NULL);
 239         free(str);
 240         str = NULL;
 241         return (modv);
 242 }