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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <ctype.h> 29 #include <stdio.h> 30 #include <string.h> 31 #include <stdlib.h> 32 #include <pthread.h> 33 #include <sys/varargs.h> 34 #include <sys/types.h> 35 #include <smbsrv/string.h> 36 #include <smbsrv/libsmb.h> 37 38 #define C2H(c) "0123456789ABCDEF"[(c)] 39 #define H2C(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ 40 ((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \ 41 ((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \ 42 '\0') 43 #define DEFAULT_SBOX_SIZE 256 44 45 /* 46 * 47 * hexdump 48 * 49 * Simple hex dump display function. Displays nbytes of buffer in hex and 50 * printable format. Non-printing characters are shown as '.'. It is safe 51 * to pass a null pointer. Each line begins with the offset. If nbytes is 52 * 0, the line will be blank except for the offset. Example output: 53 * 54 * 00000000 54 68 69 73 20 69 73 20 61 20 70 72 6F 67 72 61 This is a progra 55 * 00000010 6D 20 74 65 73 74 2E 00 m test.. 56 * 57 */ 58 void 59 hexdump_offset(unsigned char *buffer, int nbytes, unsigned long *start) 60 { 61 static char *hex = "0123456789ABCDEF"; 62 int i, count; 63 int offset; 64 unsigned char *p; 65 char ascbuf[64]; 66 char hexbuf[64]; 67 char *ap = ascbuf; 68 char *hp = hexbuf; 69 70 if ((p = buffer) == NULL) 71 return; 72 73 offset = *start; 74 75 *ap = '\0'; 76 *hp = '\0'; 77 count = 0; 78 79 for (i = 0; i < nbytes; ++i) { 80 if (i && (i % 16) == 0) { 81 smb_tracef("%06X %s %s", offset, hexbuf, ascbuf); 82 ap = ascbuf; 83 hp = hexbuf; 84 count = 0; 85 offset += 16; 86 } 87 88 ap += sprintf(ap, "%c", 89 (*p >= 0x20 && *p < 0x7F) ? *p : '.'); 90 hp += sprintf(hp, " %c%c", 91 hex[(*p >> 4) & 0x0F], hex[(*p & 0x0F)]); 92 ++p; 93 ++count; 94 } 95 96 if (count) { 97 smb_tracef("%06X %-48s %s", offset, hexbuf, ascbuf); 98 offset += count; 99 } 100 101 *start = offset; 102 } 103 104 void 105 hexdump(unsigned char *buffer, int nbytes) 106 { 107 unsigned long start = 0; 108 109 hexdump_offset(buffer, nbytes, &start); 110 } 111 112 /* 113 * bintohex 114 * 115 * Converts the given binary data (srcbuf) to 116 * its equivalent hex chars (hexbuf). 117 * 118 * hexlen should be at least twice as srclen. 119 * if hexbuf is not big enough returns 0. 120 * otherwise returns number of valid chars in 121 * hexbuf which is srclen * 2. 122 */ 123 size_t 124 bintohex(const char *srcbuf, size_t srclen, 125 char *hexbuf, size_t hexlen) 126 { 127 size_t outlen; 128 char c; 129 130 outlen = srclen << 1; 131 132 if (hexlen < outlen) 133 return (0); 134 135 while (srclen-- > 0) { 136 c = *srcbuf++; 137 *hexbuf++ = C2H(c & 0xF); 138 *hexbuf++ = C2H((c >> 4) & 0xF); 139 } 140 141 return (outlen); 142 } 143 144 /* 145 * hextobin 146 * 147 * Converts hex to binary. 148 * 149 * Assuming hexbuf only contains hex digits (chars) 150 * this function convert every two bytes of hexbuf 151 * to one byte and put it in dstbuf. 152 * 153 * hexlen should be an even number. 154 * dstlen should be at least half of hexlen. 155 * 156 * Returns 0 if sizes are not correct, otherwise 157 * returns the number of converted bytes in dstbuf 158 * which is half of hexlen. 159 */ 160 size_t 161 hextobin(const char *hexbuf, size_t hexlen, 162 char *dstbuf, size_t dstlen) 163 { 164 size_t outlen; 165 166 if ((hexlen % 2) != 0) 167 return (0); 168 169 outlen = hexlen >> 1; 170 if (dstlen < outlen) 171 return (0); 172 173 while (hexlen > 0) { 174 *dstbuf = H2C(*hexbuf) & 0x0F; 175 hexbuf++; 176 *dstbuf++ |= (H2C(*hexbuf) << 4) & 0xF0; 177 hexbuf++; 178 179 hexlen -= 2; 180 } 181 182 return (outlen); 183 } 184 185 /* 186 * trim_whitespace 187 * 188 * Trim leading and trailing whitespace chars (as defined by isspace) 189 * from a buffer. Example; if the input buffer contained " text ", 190 * it will contain "text", when we return. We assume that the buffer 191 * contains a null terminated string. A pointer to the buffer is 192 * returned. 193 */ 194 char * 195 trim_whitespace(char *buf) 196 { 197 char *p = buf; 198 char *q = buf; 199 200 if (buf == NULL) 201 return (NULL); 202 203 while (*p && isspace(*p)) 204 ++p; 205 206 while ((*q = *p++) != 0) 207 ++q; 208 209 if (q != buf) { 210 while ((--q, isspace(*q)) != 0) 211 *q = '\0'; 212 } 213 214 return (buf); 215 } 216 217 /* 218 * randomize 219 * 220 * Randomize the contents of the specified buffer. 221 */ 222 void 223 randomize(char *data, unsigned len) 224 { 225 unsigned dwlen = len / 4; 226 unsigned remlen = len % 4; 227 unsigned tmp; 228 unsigned i; /*LINTED E_BAD_PTR_CAST_ALIGN*/ 229 unsigned *p = (unsigned *)data; 230 231 for (i = 0; i < dwlen; ++i) 232 *p++ = random(); 233 234 if (remlen) { 235 tmp = random(); 236 (void) memcpy(p, &tmp, remlen); 237 } 238 } 239 240 /* 241 * This is the hash mechanism used to encrypt passwords for commands like 242 * SamrSetUserInformation. It uses a 256 byte s-box. 243 */ 244 void 245 rand_hash( 246 unsigned char *data, 247 size_t datalen, 248 unsigned char *key, 249 size_t keylen) 250 { 251 unsigned char sbox[DEFAULT_SBOX_SIZE]; 252 unsigned char tmp; 253 unsigned char index_i = 0; 254 unsigned char index_j = 0; 255 unsigned char j = 0; 256 int i; 257 258 for (i = 0; i < DEFAULT_SBOX_SIZE; ++i) 259 sbox[i] = (unsigned char)i; 260 261 for (i = 0; i < DEFAULT_SBOX_SIZE; ++i) { 262 j += (sbox[i] + key[i % keylen]); 263 264 tmp = sbox[i]; 265 sbox[i] = sbox[j]; 266 sbox[j] = tmp; 267 } 268 269 for (i = 0; i < datalen; ++i) { 270 index_i++; 271 index_j += sbox[index_i]; 272 273 tmp = sbox[index_i]; 274 sbox[index_i] = sbox[index_j]; 275 sbox[index_j] = tmp; 276 277 tmp = sbox[index_i] + sbox[index_j]; 278 data[i] = data[i] ^ sbox[tmp]; 279 } 280 } 281 282 /* 283 * strsep 284 * 285 * The strsep() function locates, in the string referenced by *stringp, the 286 * first occurrence of any character in the string delim (or the terminating 287 * `\0' character) and replaces it with a `\0'. The location of the next 288 * character after the delimiter character (or NULL, if the end of the 289 * string was reached) is stored in *stringp. The original value of 290 * *stringp is returned. 291 * 292 * If *stringp is initially NULL, strsep() returns NULL. 293 */ 294 char * 295 strsep(char **stringp, const char *delim) 296 { 297 char *s; 298 const char *spanp; 299 int c, sc; 300 char *tok; 301 302 if ((s = *stringp) == NULL) 303 return (NULL); 304 305 for (tok = s; ; ) { 306 c = *s++; 307 spanp = delim; 308 do { 309 if ((sc = *spanp++) == c) { 310 if (c == 0) 311 s = NULL; 312 else 313 s[-1] = 0; 314 *stringp = s; 315 return (tok); 316 } 317 } while (sc != 0); 318 } 319 /* NOTREACHED */ 320 } 321