1 /* $FreeBSD$ */ 2 3 #ifdef SRA 4 #include <sys/types.h> 5 #include <arpa/telnet.h> 6 #include <stdio.h> 7 #ifdef __STDC__ 8 #include <stdlib.h> 9 #endif 10 #ifdef NO_STRING_H 11 #include <strings.h> 12 #else 13 #include <string.h> 14 #endif 15 16 #include "auth.h" 17 #include "misc.h" 18 #include "encrypt.h" 19 #include "pk.h" 20 21 char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1]; 22 char *user,*pass,*xuser,*xpass; 23 DesData ck; 24 IdeaData ik; 25 26 extern int auth_debug_mode; 27 static sra_valid = 0; 28 static passwd_sent = 0; 29 30 static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 31 AUTHTYPE_SRA, }; 32 33 #define SRA_KEY 0 34 #define SRA_USER 1 35 #define SRA_CONTINUE 2 36 #define SRA_PASS 3 37 #define SRA_ACCEPT 4 38 #define SRA_REJECT 5 39 40 /* support routine to send out authentication message */ 41 static int Data(ap, type, d, c) 42 Authenticator *ap; 43 int type; 44 void *d; 45 int c; 46 { 47 unsigned char *p = str_data + 4; 48 unsigned char *cd = (unsigned char *)d; 49 50 if (c == -1) 51 c = strlen((char *)cd); 52 53 if (auth_debug_mode) { 54 printf("%s:%d: [%d] (%d)", 55 str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 56 str_data[3], 57 type, c); 58 printd(d, c); 59 printf("\r\n"); 60 } 61 *p++ = ap->type; 62 *p++ = ap->way; 63 *p++ = type; 64 while (c-- > 0) { 65 if ((*p++ = *cd++) == IAC) 66 *p++ = IAC; 67 } 68 *p++ = IAC; 69 *p++ = SE; 70 if (str_data[3] == TELQUAL_IS) 71 printsub('>', &str_data[2], p - (&str_data[2])); 72 return(net_write(str_data, p - str_data)); 73 } 74 75 int sra_init(ap, server) 76 Authenticator *ap; 77 int server; 78 { 79 if (server) 80 str_data[3] = TELQUAL_REPLY; 81 else 82 str_data[3] = TELQUAL_IS; 83 84 user = (char *)malloc(256); 85 xuser = (char *)malloc(512); 86 pass = (char *)malloc(256); 87 xpass = (char *)malloc(512); 88 passwd_sent = 0; 89 90 genkeys(pka,ska); 91 return(1); 92 } 93 94 /* client received a go-ahead for sra */ 95 int sra_send(ap) 96 Authenticator *ap; 97 { 98 /* send PKA */ 99 100 if (auth_debug_mode) 101 printf("Sent PKA to server.\r\n" ); 102 printf("Trying SRA secure login:\r\n"); 103 if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { 104 if (auth_debug_mode) 105 printf("Not enough room for authentication data\r\n"); 106 return(0); 107 } 108 109 return(1); 110 } 111 112 /* server received an IS -- could be SRA KEY, USER, or PASS */ 113 void sra_is(ap, data, cnt) 114 Authenticator *ap; 115 unsigned char *data; 116 int cnt; 117 { 118 int valid; 119 Session_Key skey; 120 121 if (cnt-- < 1) 122 return; 123 switch (*data++) { 124 125 case SRA_KEY: 126 if (cnt < HEXKEYBYTES) { 127 Data(ap, SRA_REJECT, (void *)0, 0); 128 auth_finished(ap, AUTH_USER); 129 if (auth_debug_mode) { 130 printf("SRA user rejected for bad PKB\r\n"); 131 } 132 return; 133 } 134 if (auth_debug_mode) 135 printf("Sent pka\r\n"); 136 if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) { 137 if (auth_debug_mode) 138 printf("Not enough room\r\n"); 139 return; 140 } 141 memcpy(pkb,data,HEXKEYBYTES); 142 pkb[HEXKEYBYTES] = '\0'; 143 common_key(ska,pkb,&ik,&ck); 144 break; 145 146 case SRA_USER: 147 /* decode KAB(u) */ 148 memcpy(xuser,data,cnt); 149 xuser[cnt] = '\0'; 150 pk_decode(xuser,user,&ck); 151 auth_encrypt_user(user); 152 Data(ap, SRA_CONTINUE, (void *)0, 0); 153 154 break; 155 156 case SRA_PASS: 157 /* decode KAB(P) */ 158 memcpy(xpass,data,cnt); 159 xpass[cnt] = '\0'; 160 pk_decode(xpass,pass,&ck); 161 162 /* check user's password */ 163 valid = check_user(user,pass); 164 165 if(valid) { 166 Data(ap, SRA_ACCEPT, (void *)0, 0); 167 #ifdef DES_ENCRYPTION 168 skey.data = ck; 169 skey.type = SK_DES; 170 skey.length = 8; 171 encrypt_session_key(&skey, 1); 172 #endif 173 174 sra_valid = 1; 175 auth_finished(ap, AUTH_VALID); 176 if (auth_debug_mode) { 177 printf("SRA user accepted\r\n"); 178 } 179 } 180 else { 181 Data(ap, SRA_CONTINUE, (void *)0, 0); 182 /* 183 Data(ap, SRA_REJECT, (void *)0, 0); 184 sra_valid = 0; 185 auth_finished(ap, AUTH_REJECT); 186 */ 187 if (auth_debug_mode) { 188 printf("SRA user failed\r\n"); 189 } 190 } 191 break; 192 193 default: 194 if (auth_debug_mode) 195 printf("Unknown SRA option %d\r\n", data[-1]); 196 Data(ap, SRA_REJECT, 0, 0); 197 sra_valid = 0; 198 auth_finished(ap, AUTH_REJECT); 199 break; 200 } 201 } 202 203 extern char *getpass(); 204 205 /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */ 206 void sra_reply(ap, data, cnt) 207 Authenticator *ap; 208 unsigned char *data; 209 int cnt; 210 { 211 extern char *telnet_gets(); 212 char uprompt[256],tuser[256]; 213 Session_Key skey; 214 int i; 215 216 if (cnt-- < 1) 217 return; 218 switch (*data++) { 219 220 case SRA_KEY: 221 /* calculate common key */ 222 if (cnt < HEXKEYBYTES) { 223 if (auth_debug_mode) { 224 printf("SRA user rejected for bad PKB\r\n"); 225 } 226 return; 227 } 228 memcpy(pkb,data,HEXKEYBYTES); 229 pkb[HEXKEYBYTES] = '\0'; 230 231 common_key(ska,pkb,&ik,&ck); 232 233 enc_user: 234 235 /* encode user */ 236 memset(tuser,0,sizeof(tuser)); 237 sprintf(uprompt,"User (%s): ",UserNameRequested); 238 telnet_gets(uprompt,tuser,255,1); 239 if (tuser[0] == '\n' || tuser[0] == '\r' ) 240 strcpy(user,UserNameRequested); 241 else { 242 /* telnet_gets leaves the newline on */ 243 for(i=0;i<sizeof(tuser);i++) { 244 if (tuser[i] == '\n') { 245 tuser[i] = '\0'; 246 break; 247 } 248 } 249 strcpy(user,tuser); 250 } 251 pk_encode(user,xuser,&ck); 252 253 /* send it off */ 254 if (auth_debug_mode) 255 printf("Sent KAB(U)\r\n"); 256 if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) { 257 if (auth_debug_mode) 258 printf("Not enough room\r\n"); 259 return; 260 } 261 break; 262 263 case SRA_CONTINUE: 264 if (passwd_sent) { 265 passwd_sent = 0; 266 printf("[ SRA login failed ]\r\n"); 267 goto enc_user; 268 } 269 /* encode password */ 270 memset(pass,0,sizeof(pass)); 271 telnet_gets("Password: ",pass,255,0); 272 pk_encode(pass,xpass,&ck); 273 /* send it off */ 274 if (auth_debug_mode) 275 printf("Sent KAB(P)\r\n"); 276 if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) { 277 if (auth_debug_mode) 278 printf("Not enough room\r\n"); 279 return; 280 } 281 passwd_sent = 1; 282 break; 283 284 case SRA_REJECT: 285 printf("[ SRA refuses authentication ]\r\n"); 286 printf("Trying plaintext login:\r\n"); 287 auth_finished(0,AUTH_REJECT); 288 return; 289 290 case SRA_ACCEPT: 291 printf("[ SRA accepts you ]\r\n"); 292 #ifdef DES_ENCRYPTION 293 skey.data = ck; 294 skey.type = SK_DES; 295 skey.length = 8; 296 encrypt_session_key(&skey, 0); 297 #endif 298 299 auth_finished(ap, AUTH_VALID); 300 return; 301 default: 302 if (auth_debug_mode) 303 printf("Unknown SRA option %d\r\n", data[-1]); 304 return; 305 } 306 } 307 308 int sra_status(ap, name, level) 309 Authenticator *ap; 310 char *name; 311 int level; 312 { 313 if (level < AUTH_USER) 314 return(level); 315 if (UserNameRequested && sra_valid) { 316 strcpy(name, UserNameRequested); 317 return(AUTH_VALID); 318 } else 319 return(AUTH_USER); 320 } 321 322 #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 323 #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 324 325 void sra_printsub(data, cnt, buf, buflen) 326 unsigned char *data, *buf; 327 int cnt, buflen; 328 { 329 char lbuf[32]; 330 register int i; 331 332 buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 333 buflen -= 1; 334 335 switch(data[3]) { 336 337 case SRA_CONTINUE: 338 strncpy((char *)buf, " CONTINUE ", buflen); 339 goto common; 340 341 case SRA_REJECT: /* Rejected (reason might follow) */ 342 strncpy((char *)buf, " REJECT ", buflen); 343 goto common; 344 345 case SRA_ACCEPT: /* Accepted (name might follow) */ 346 strncpy((char *)buf, " ACCEPT ", buflen); 347 348 common: 349 BUMP(buf, buflen); 350 if (cnt <= 4) 351 break; 352 ADDC(buf, buflen, '"'); 353 for (i = 4; i < cnt; i++) 354 ADDC(buf, buflen, data[i]); 355 ADDC(buf, buflen, '"'); 356 ADDC(buf, buflen, '\0'); 357 break; 358 359 case SRA_KEY: /* Authentication data follows */ 360 strncpy((char *)buf, " KEY ", buflen); 361 goto common2; 362 363 case SRA_USER: 364 strncpy((char *)buf, " USER ", buflen); 365 goto common2; 366 367 case SRA_PASS: 368 strncpy((char *)buf, " PASS ", buflen); 369 goto common2; 370 371 default: 372 sprintf(lbuf, " %d (unknown)", data[3]); 373 strncpy((char *)buf, lbuf, buflen); 374 common2: 375 BUMP(buf, buflen); 376 for (i = 4; i < cnt; i++) { 377 sprintf(lbuf, " %d", data[i]); 378 strncpy((char *)buf, lbuf, buflen); 379 BUMP(buf, buflen); 380 } 381 break; 382 } 383 } 384 385 struct passwd *pw; 386 387 /* 388 * Helper function for sgetpwnam(). 389 */ 390 char * 391 sgetsave(s) 392 char *s; 393 { 394 char *new = malloc((unsigned) strlen(s) + 1); 395 396 if (new == NULL) { 397 return(NULL); 398 } 399 (void) strcpy(new, s); 400 return (new); 401 } 402 403 #include <pwd.h> 404 #include <syslog.h> 405 #ifdef USE_SHADOW 406 #include <shadow.h> 407 #endif 408 409 410 struct passwd * 411 sgetpwnam(name) 412 char *name; 413 { 414 static struct passwd save; 415 register struct passwd *p; 416 char *sgetsave(); 417 418 if ((p = getpwnam(name)) == NULL) 419 return (p); 420 if (save.pw_name) { 421 free(save.pw_name); 422 free(save.pw_passwd); 423 free(save.pw_gecos); 424 free(save.pw_dir); 425 free(save.pw_shell); 426 } 427 save = *p; 428 save.pw_name = sgetsave(p->pw_name); 429 save.pw_passwd = sgetsave(p->pw_passwd); 430 save.pw_gecos = sgetsave(p->pw_gecos); 431 save.pw_dir = sgetsave(p->pw_dir); 432 save.pw_shell = sgetsave(p->pw_shell); 433 #if 0 434 syslog(LOG_WARNING,"%s\n",save.pw_name); 435 syslog(LOG_WARNING,"%s\n",save.pw_passwd); 436 syslog(LOG_WARNING,"%s\n",save.pw_gecos); 437 syslog(LOG_WARNING,"%s\n",save.pw_dir); 438 #endif 439 #ifdef USE_SHADOW 440 { 441 struct spwd *sp; 442 sp = getspnam(name); 443 free(save.pw_passwd); 444 save.pw_passwd = sgetsave(sp->sp_pwdp); 445 } 446 #endif 447 return (&save); 448 } 449 450 char *crypt(); 451 452 int check_user(name, pass) 453 char *name; 454 char *pass; 455 { 456 register char *cp; 457 char *xpasswd, *salt; 458 459 if (pw = sgetpwnam(name)) { 460 if (pw->pw_shell == NULL) { 461 pw = (struct passwd *) NULL; 462 return(0); 463 } 464 465 salt = pw->pw_passwd; 466 xpasswd = crypt(pass, salt); 467 /* The strcmp does not catch null passwords! */ 468 if (pw == NULL || *pw->pw_passwd == '\0' || 469 strcmp(xpasswd, pw->pw_passwd)) { 470 pw = (struct passwd *) NULL; 471 return(0); 472 } 473 return(1); 474 } 475 return(0); 476 } 477 478 479 #endif 480 481