1 /*- 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * $FreeBSD$ 34 */ 35 36 #ifndef lint 37 static char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 5/30/95"; 38 #endif /* not lint */ 39 40 41 #ifdef KRB4_ENCPWD 42 /* 43 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION 44 * ALL RIGHTS RESERVED 45 * 46 * "Digital Equipment Corporation authorizes the reproduction, 47 * distribution and modification of this software subject to the following 48 * restrictions: 49 * 50 * 1. Any partial or whole copy of this software, or any modification 51 * thereof, must include this copyright notice in its entirety. 52 * 53 * 2. This software is supplied "as is" with no warranty of any kind, 54 * expressed or implied, for any purpose, including any warranty of fitness 55 * or merchantibility. DIGITAL assumes no responsibility for the use or 56 * reliability of this software, nor promises to provide any form of 57 * support for it on any basis. 58 * 59 * 3. Distribution of this software is authorized only if no profit or 60 * remuneration of any kind is received in exchange for such distribution. 61 * 62 * 4. This software produces public key authentication certificates 63 * bearing an expiration date established by DIGITAL and RSA Data 64 * Security, Inc. It may cease to generate certificates after the expiration 65 * date. Any modification of this software that changes or defeats 66 * the expiration date or its effect is unauthorized. 67 * 68 * 5. Software that will renew or extend the expiration date of 69 * authentication certificates produced by this software may be obtained 70 * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA 71 * 94065, (415)595-8782, or from DIGITAL" 72 * 73 */ 74 75 #include <sys/types.h> 76 #include <arpa/telnet.h> 77 #include <pwd.h> 78 #include <stdio.h> 79 80 #include <openssl/des.h> 81 #include <krb.h> 82 #ifdef __STDC__ 83 #include <stdlib.h> 84 #endif 85 #ifdef NO_STRING_H 86 #include <strings.h> 87 #else 88 #include <string.h> 89 #endif 90 91 #include "encrypt.h" 92 #include "auth.h" 93 #include "misc.h" 94 95 int krb_mk_encpwd_req P((KTEXT, char *, char *, char *, char *, char *, char *)); 96 int krb_rd_encpwd_req P((KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *)); 97 98 extern auth_debug_mode; 99 100 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 101 AUTHTYPE_KRB4_ENCPWD, }; 102 static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 103 TELQUAL_NAME, }; 104 105 #define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */ 106 #define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ 107 #define KRB4_ENCPWD_ACCEPT 2 /* Accepted */ 108 #define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */ 109 #define KRB4_ENCPWD_ACK 4 /* Acknowledge */ 110 111 #define KRB_SERVICE_NAME "rcmd" 112 113 static KTEXT_ST auth; 114 static char name[ANAME_SZ]; 115 static char user_passwd[ANAME_SZ]; 116 static AUTH_DAT adat = { 0 }; 117 #ifdef ENCRYPTION 118 static Block session_key = { 0 }; 119 #endif /* ENCRYPTION */ 120 static char challenge[REALM_SZ]; 121 122 static int 123 Data(ap, type, d, c) 124 Authenticator *ap; 125 int type; 126 void *d; 127 int c; 128 { 129 unsigned char *p = str_data + 4; 130 unsigned char *cd = (unsigned char *)d; 131 132 if (c == -1) 133 c = strlen((char *)cd); 134 135 if (0) { 136 printf("%s:%d: [%d] (%d)", 137 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 138 str_data[3], 139 type, c); 140 printd(d, c); 141 printf("\r\n"); 142 } 143 *p++ = ap->type; 144 *p++ = ap->way; 145 *p++ = type; 146 while (c-- > 0) { 147 if ((*p++ = *cd++) == IAC) 148 *p++ = IAC; 149 } 150 *p++ = IAC; 151 *p++ = SE; 152 if (str_data[3] == TELQUAL_IS) 153 printsub('>', &str_data[2], p - (&str_data[2])); 154 return(net_write(str_data, p - str_data)); 155 } 156 157 int 158 krb4encpwd_init(ap, server) 159 Authenticator *ap; 160 int server; 161 { 162 char hostname[80], *cp, *realm; 163 C_Block skey; 164 165 if (server) { 166 str_data[3] = TELQUAL_REPLY; 167 } else { 168 str_data[3] = TELQUAL_IS; 169 gethostname(hostname, sizeof(hostname)); 170 realm = krb_realmofhost(hostname); 171 cp = strchr(hostname, '.'); 172 if (*cp != NULL) *cp = NULL; 173 if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0, 174 KEYFILE, (char *)skey)) { 175 return(0); 176 } 177 } 178 return(1); 179 } 180 181 int 182 krb4encpwd_send(ap) 183 Authenticator *ap; 184 { 185 186 printf("[ Trying KRB4ENCPWD ... ]\n"); 187 if (!UserNameRequested) { 188 return(0); 189 } 190 if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { 191 return(0); 192 } 193 194 if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) { 195 return(0); 196 } 197 198 return(1); 199 } 200 201 void 202 krb4encpwd_is(ap, data, cnt) 203 Authenticator *ap; 204 unsigned char *data; 205 int cnt; 206 { 207 Session_Key skey; 208 Block datablock; 209 char r_passwd[ANAME_SZ], r_user[ANAME_SZ]; 210 char lhostname[ANAME_SZ], *cp; 211 int r; 212 time_t now; 213 214 if (cnt-- < 1) 215 return; 216 switch (*data++) { 217 case KRB4_ENCPWD_AUTH: 218 memmove((void *)auth.dat, (void *)data, auth.length = cnt); 219 220 gethostname(lhostname, sizeof(lhostname)); 221 if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; 222 223 if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) { 224 Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1); 225 auth_finished(ap, AUTH_REJECT); 226 return; 227 } 228 auth_encrypt_userpwd(r_passwd); 229 if (passwdok(UserNameRequested, UserPassword) == 0) { 230 /* 231 * illegal username and password 232 */ 233 Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1); 234 auth_finished(ap, AUTH_REJECT); 235 return; 236 } 237 238 memmove((void *)session_key, (void *)adat.session, sizeof(Block)); 239 Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0); 240 auth_finished(ap, AUTH_USER); 241 break; 242 243 case KRB4_ENCPWD_CHALLENGE: 244 /* 245 * Take the received random challenge text and save 246 * for future authentication. 247 */ 248 memmove((void *)challenge, (void *)data, sizeof(Block)); 249 break; 250 251 252 case KRB4_ENCPWD_ACK: 253 /* 254 * Receive ack, if mutual then send random challenge 255 */ 256 257 /* 258 * If we are doing mutual authentication, get set up to send 259 * the challenge, and verify it when the response comes back. 260 */ 261 262 if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) { 263 register int i; 264 265 time(&now); 266 sprintf(challenge, "%x", now); 267 Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge)); 268 } 269 break; 270 271 default: 272 Data(ap, KRB4_ENCPWD_REJECT, 0, 0); 273 break; 274 } 275 } 276 277 278 void 279 krb4encpwd_reply(ap, data, cnt) 280 Authenticator *ap; 281 unsigned char *data; 282 int cnt; 283 { 284 Session_Key skey; 285 KTEXT_ST krb_token; 286 Block enckey; 287 CREDENTIALS cred; 288 int r; 289 char randchal[REALM_SZ], instance[ANAME_SZ], *cp; 290 char hostname[80], *realm; 291 292 if (cnt-- < 1) 293 return; 294 switch (*data++) { 295 case KRB4_ENCPWD_REJECT: 296 if (cnt > 0) { 297 printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n", 298 cnt, data); 299 } else 300 printf("[ KRB4_ENCPWD refuses authentication ]\r\n"); 301 auth_send_retry(); 302 return; 303 case KRB4_ENCPWD_ACCEPT: 304 printf("[ KRB4_ENCPWD accepts you ]\n"); 305 auth_finished(ap, AUTH_USER); 306 return; 307 case KRB4_ENCPWD_CHALLENGE: 308 /* 309 * Verify that the response to the challenge is correct. 310 */ 311 312 gethostname(hostname, sizeof(hostname)); 313 realm = krb_realmofhost(hostname); 314 memmove((void *)challenge, (void *)data, cnt); 315 memset(user_passwd, 0, sizeof(user_passwd)); 316 local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); 317 UserPassword = user_passwd; 318 Challenge = challenge; 319 strcpy(instance, RemoteHostName); 320 if ((cp = strchr(instance, '.')) != 0) *cp = '\0'; 321 322 if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) { 323 krb_token.length = 0; 324 } 325 326 if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) { 327 return; 328 } 329 330 break; 331 332 default: 333 return; 334 } 335 } 336 337 int 338 krb4encpwd_status(ap, name, level) 339 Authenticator *ap; 340 char *name; 341 int level; 342 { 343 344 if (level < AUTH_USER) 345 return(level); 346 347 if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) { 348 strcpy(name, UserNameRequested); 349 return(AUTH_VALID); 350 } else { 351 return(AUTH_USER); 352 } 353 } 354 355 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 356 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 357 358 void 359 krb4encpwd_printsub(data, cnt, buf, buflen) 360 unsigned char *data, *buf; 361 int cnt, buflen; 362 { 363 char lbuf[32]; 364 register int i; 365 366 buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 367 buflen -= 1; 368 369 switch(data[3]) { 370 case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */ 371 strncpy((char *)buf, " REJECT ", buflen); 372 goto common; 373 374 case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */ 375 strncpy((char *)buf, " ACCEPT ", buflen); 376 common: 377 BUMP(buf, buflen); 378 if (cnt <= 4) 379 break; 380 ADDC(buf, buflen, '"'); 381 for (i = 4; i < cnt; i++) 382 ADDC(buf, buflen, data[i]); 383 ADDC(buf, buflen, '"'); 384 ADDC(buf, buflen, '\0'); 385 break; 386 387 case KRB4_ENCPWD_AUTH: /* Authentication data follows */ 388 strncpy((char *)buf, " AUTH", buflen); 389 goto common2; 390 391 case KRB4_ENCPWD_CHALLENGE: 392 strncpy((char *)buf, " CHALLENGE", buflen); 393 goto common2; 394 395 case KRB4_ENCPWD_ACK: 396 strncpy((char *)buf, " ACK", buflen); 397 goto common2; 398 399 default: 400 sprintf(lbuf, " %d (unknown)", data[3]); 401 strncpy((char *)buf, lbuf, buflen); 402 common2: 403 BUMP(buf, buflen); 404 for (i = 4; i < cnt; i++) { 405 sprintf(lbuf, " %d", data[i]); 406 strncpy((char *)buf, lbuf, buflen); 407 BUMP(buf, buflen); 408 } 409 break; 410 } 411 } 412 413 int passwdok(name, passwd) 414 char *name, *passwd; 415 { 416 char *crypt(); 417 char *salt, *p; 418 struct passwd *pwd; 419 int passwdok_status = 0; 420 421 if (pwd = getpwnam(name)) 422 salt = pwd->pw_passwd; 423 else salt = "xx"; 424 425 p = crypt(passwd, salt); 426 427 if (pwd && !strcmp(p, pwd->pw_passwd)) { 428 passwdok_status = 1; 429 } else passwdok_status = 0; 430 return(passwdok_status); 431 } 432 433 #endif 434 435 #ifdef notdef 436 437 prkey(msg, key) 438 char *msg; 439 unsigned char *key; 440 { 441 register int i; 442 printf("%s:", msg); 443 for (i = 0; i < 8; i++) 444 printf(" %3d", key[i]); 445 printf("\r\n"); 446 } 447 #endif 448