129088Smarkm/*- 229088Smarkm * Copyright (c) 1992, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 3484305Smarkm#include <sys/cdefs.h> 3587139Smarkm 3684305Smarkm__FBSDID("$FreeBSD$"); 3784305Smarkm 3829088Smarkm#ifndef lint 3929088Smarkmstatic char sccsid[] = "@(#)rsaencpwd.c 8.3 (Berkeley) 5/30/95"; 4029088Smarkm#endif /* not lint */ 4129088Smarkm 4229088Smarkm 4329088Smarkm#ifdef RSA_ENCPWD 4429088Smarkm/* 4529088Smarkm * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION 4629088Smarkm * ALL RIGHTS RESERVED 4729088Smarkm * 4829088Smarkm * "Digital Equipment Corporation authorizes the reproduction, 4929088Smarkm * distribution and modification of this software subject to the following 5029088Smarkm * restrictions: 5129088Smarkm * 5229088Smarkm * 1. Any partial or whole copy of this software, or any modification 5329088Smarkm * thereof, must include this copyright notice in its entirety. 5429088Smarkm * 5529088Smarkm * 2. This software is supplied "as is" with no warranty of any kind, 5629088Smarkm * expressed or implied, for any purpose, including any warranty of fitness 5729088Smarkm * or merchantibility. DIGITAL assumes no responsibility for the use or 5829088Smarkm * reliability of this software, nor promises to provide any form of 5929088Smarkm * support for it on any basis. 6029088Smarkm * 6129088Smarkm * 3. Distribution of this software is authorized only if no profit or 6229088Smarkm * remuneration of any kind is received in exchange for such distribution. 6329088Smarkm * 6429088Smarkm * 4. This software produces public key authentication certificates 6529088Smarkm * bearing an expiration date established by DIGITAL and RSA Data 6629088Smarkm * Security, Inc. It may cease to generate certificates after the expiration 6729088Smarkm * date. Any modification of this software that changes or defeats 6829088Smarkm * the expiration date or its effect is unauthorized. 6929088Smarkm * 7029088Smarkm * 5. Software that will renew or extend the expiration date of 7129088Smarkm * authentication certificates produced by this software may be obtained 7229088Smarkm * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA 7329088Smarkm * 94065, (415)595-8782, or from DIGITAL" 7429088Smarkm * 7529088Smarkm */ 7629088Smarkm 7729088Smarkm#include <sys/types.h> 7829088Smarkm#include <arpa/telnet.h> 7929088Smarkm#include <pwd.h> 8029088Smarkm#include <stdio.h> 8129088Smarkm#include <stdlib.h> 8229088Smarkm#include <string.h> 8329088Smarkm 8429088Smarkm#include "encrypt.h" 8529088Smarkm#include "auth.h" 8629088Smarkm#include "misc.h" 8729088Smarkm#include "cdc.h" 8829088Smarkm 8929088Smarkmextern auth_debug_mode; 9029088Smarkm 9129088Smarkmstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 9229088Smarkm AUTHTYPE_RSA_ENCPWD, }; 9329088Smarkmstatic unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 9429088Smarkm TELQUAL_NAME, }; 9529088Smarkm 9629088Smarkm#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */ 9729088Smarkm#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ 9829088Smarkm#define RSA_ENCPWD_ACCEPT 2 /* Accepted */ 9929088Smarkm#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */ 10029088Smarkm 10129088Smarkm#define NAME_SZ 40 10229088Smarkm#define CHAL_SZ 20 10329088Smarkm#define PWD_SZ 40 10429088Smarkm 10529088Smarkmstatic KTEXT_ST auth; 10629088Smarkmstatic char name[NAME_SZ]; 10729088Smarkmstatic char user_passwd[PWD_SZ]; 10829088Smarkmstatic char key_file[2*NAME_SZ]; 10929088Smarkmstatic char lhostname[NAME_SZ]; 11029088Smarkmstatic char challenge[CHAL_SZ]; 11129088Smarkmstatic int challenge_len; 11229088Smarkm 11329088Smarkm static int 11429088SmarkmData(ap, type, d, c) 11529088Smarkm Authenticator *ap; 11629088Smarkm int type; 11729088Smarkm void *d; 11829088Smarkm int c; 11929088Smarkm{ 12029088Smarkm unsigned char *p = str_data + 4; 12129088Smarkm unsigned char *cd = (unsigned char *)d; 12229088Smarkm 12329088Smarkm if (c == -1) 12429088Smarkm c = strlen((char *)cd); 12529088Smarkm 12629088Smarkm if (0) { 12729088Smarkm printf("%s:%d: [%d] (%d)", 12829088Smarkm str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 12929088Smarkm str_data[3], 13029088Smarkm type, c); 13129088Smarkm printd(d, c); 13229088Smarkm printf("\r\n"); 13329088Smarkm } 13429088Smarkm *p++ = ap->type; 13529088Smarkm *p++ = ap->way; 13629088Smarkm if (type != NULL) *p++ = type; 13729088Smarkm while (c-- > 0) { 13829088Smarkm if ((*p++ = *cd++) == IAC) 13929088Smarkm *p++ = IAC; 14029088Smarkm } 14129088Smarkm *p++ = IAC; 14229088Smarkm *p++ = SE; 14329088Smarkm if (str_data[3] == TELQUAL_IS) 14429088Smarkm printsub('>', &str_data[2], p - (&str_data[2])); 14529088Smarkm return(net_write(str_data, p - str_data)); 14629088Smarkm} 14729088Smarkm 14829088Smarkm int 14929088Smarkmrsaencpwd_init(ap, server) 15029088Smarkm Authenticator *ap; 15129088Smarkm int server; 15229088Smarkm{ 15329088Smarkm char *cp; 15429088Smarkm FILE *fp; 15529088Smarkm 15629088Smarkm if (server) { 15729088Smarkm str_data[3] = TELQUAL_REPLY; 15829088Smarkm memset(key_file, 0, sizeof(key_file)); 15929088Smarkm gethostname(lhostname, sizeof(lhostname)); 16029088Smarkm if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; 16129088Smarkm strcpy(key_file, "/etc/."); 16229088Smarkm strcat(key_file, lhostname); 16329088Smarkm strcat(key_file, "_privkey"); 16429088Smarkm if ((fp=fopen(key_file, "r"))==NULL) return(0); 16529088Smarkm fclose(fp); 16629088Smarkm } else { 16729088Smarkm str_data[3] = TELQUAL_IS; 16829088Smarkm } 16929088Smarkm return(1); 17029088Smarkm} 17129088Smarkm 17229088Smarkm int 17329088Smarkmrsaencpwd_send(ap) 17429088Smarkm Authenticator *ap; 17529088Smarkm{ 17629088Smarkm 17729088Smarkm printf("[ Trying RSAENCPWD ... ]\n"); 17829088Smarkm if (!UserNameRequested) { 17929088Smarkm return(0); 18029088Smarkm } 18129088Smarkm if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { 18229088Smarkm return(0); 18329088Smarkm } 18429088Smarkm if (!Data(ap, NULL, (void *)NULL, 0)) { 18529088Smarkm return(0); 18629088Smarkm } 18729088Smarkm 18829088Smarkm 18929088Smarkm return(1); 19029088Smarkm} 19129088Smarkm 19229088Smarkm void 19329088Smarkmrsaencpwd_is(ap, data, cnt) 19429088Smarkm Authenticator *ap; 19529088Smarkm unsigned char *data; 19629088Smarkm int cnt; 19729088Smarkm{ 19829088Smarkm Session_Key skey; 19929088Smarkm Block datablock; 20029088Smarkm char r_passwd[PWD_SZ], r_user[NAME_SZ]; 20129088Smarkm char *cp, key[160]; 20229088Smarkm char chalkey[160], *ptr; 20329088Smarkm FILE *fp; 20429088Smarkm int r, i, j, chalkey_len, len; 20529088Smarkm time_t now; 20629088Smarkm 20729088Smarkm cnt--; 20829088Smarkm switch (*data++) { 20929088Smarkm case RSA_ENCPWD_AUTH: 21029088Smarkm memmove((void *)auth.dat, (void *)data, auth.length = cnt); 21129088Smarkm 21229088Smarkm if ((fp=fopen(key_file, "r"))==NULL) { 21329088Smarkm Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); 21429088Smarkm auth_finished(ap, AUTH_REJECT); 21529088Smarkm return; 21629088Smarkm } 21729088Smarkm /* 21829088Smarkm * get privkey 21929088Smarkm */ 22029088Smarkm fscanf(fp, "%x;", &len); 22129088Smarkm for (i=0;i<len;i++) { 22229088Smarkm j = getc(fp); key[i]=j; 22329088Smarkm } 22429088Smarkm fclose(fp); 22529088Smarkm 22629088Smarkm r = accept_rsa_encpwd(&auth, key, challenge, 22729088Smarkm challenge_len, r_passwd); 22829088Smarkm if (r < 0) { 22929088Smarkm Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); 23029088Smarkm auth_finished(ap, AUTH_REJECT); 23129088Smarkm return; 23229088Smarkm } 23329088Smarkm auth_encrypt_userpwd(r_passwd); 23429088Smarkm if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) { 23529088Smarkm /* 23629088Smarkm * illegal username and password 23729088Smarkm */ 23829088Smarkm Data(ap, RSA_ENCPWD_REJECT, (void *)"Illegal password", -1); 23929088Smarkm auth_finished(ap, AUTH_REJECT); 24029088Smarkm return; 24129088Smarkm } 24229088Smarkm 24329088Smarkm Data(ap, RSA_ENCPWD_ACCEPT, (void *)0, 0); 24429088Smarkm auth_finished(ap, AUTH_USER); 24529088Smarkm break; 24629088Smarkm 24729088Smarkm 24829088Smarkm case IAC: 24929088Smarkm 25029088Smarkm /* 25129088Smarkm * If we are doing mutual authentication, get set up to send 25229088Smarkm * the challenge, and verify it when the response comes back. 25329088Smarkm */ 25429088Smarkm if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) { 25529088Smarkm register int i; 25629088Smarkm 25729088Smarkm 25829088Smarkm time(&now); 25929088Smarkm if ((now % 2) == 0) { 26029088Smarkm sprintf(challenge, "%x", now); 26129088Smarkm challenge_len = strlen(challenge); 26229088Smarkm } else { 26329088Smarkm strcpy(challenge, "randchal"); 26429088Smarkm challenge_len = 8; 26529088Smarkm } 26629088Smarkm 26729088Smarkm if ((fp=fopen(key_file, "r"))==NULL) { 26829088Smarkm Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1); 26929088Smarkm auth_finished(ap, AUTH_REJECT); 27029088Smarkm return; 27129088Smarkm } 27229088Smarkm /* 27329088Smarkm * skip privkey 27429088Smarkm */ 27529088Smarkm fscanf(fp, "%x;", &len); 27629088Smarkm for (i=0;i<len;i++) { 27729088Smarkm j = getc(fp); 27829088Smarkm } 27929088Smarkm /* 28029088Smarkm * get pubkey 28129088Smarkm */ 28229088Smarkm fscanf(fp, "%x;", &len); 28329088Smarkm for (i=0;i<len;i++) { 28429088Smarkm j = getc(fp); key[i]=j; 28529088Smarkm } 28629088Smarkm fclose(fp); 28729088Smarkm chalkey[0] = 0x30; 28829088Smarkm ptr = (char *) &chalkey[1]; 28929088Smarkm chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len; 29029088Smarkm EncodeLength(ptr, chalkey_len); 29129088Smarkm ptr +=NumEncodeLengthOctets(chalkey_len); 29229088Smarkm *ptr++ = 0x04; /* OCTET STRING */ 29329088Smarkm *ptr++ = challenge_len; 29429088Smarkm memmove(ptr, challenge, challenge_len); 29529088Smarkm ptr += challenge_len; 29629088Smarkm *ptr++ = 0x04; /* OCTET STRING */ 29729088Smarkm EncodeLength(ptr, i); 29829088Smarkm ptr += NumEncodeLengthOctets(i); 29929088Smarkm memmove(ptr, key, i); 30029088Smarkm chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len; 30129088Smarkm Data(ap, RSA_ENCPWD_CHALLENGEKEY, (void *)chalkey, chalkey_len); 30229088Smarkm } 30329088Smarkm break; 30429088Smarkm 30529088Smarkm default: 30629088Smarkm Data(ap, RSA_ENCPWD_REJECT, 0, 0); 30729088Smarkm break; 30829088Smarkm } 30929088Smarkm} 31029088Smarkm 31129088Smarkm 31229088Smarkm void 31329088Smarkmrsaencpwd_reply(ap, data, cnt) 31429088Smarkm Authenticator *ap; 31529088Smarkm unsigned char *data; 31629088Smarkm int cnt; 31729088Smarkm{ 31829088Smarkm Session_Key skey; 31929088Smarkm KTEXT_ST token; 32029088Smarkm Block enckey; 32129088Smarkm int r, pubkey_len; 32229088Smarkm char randchal[CHAL_SZ], *cp; 32329088Smarkm char chalkey[160], pubkey[128], *ptr; 32429088Smarkm 32529088Smarkm if (cnt-- < 1) 32629088Smarkm return; 32729088Smarkm switch (*data++) { 32829088Smarkm case RSA_ENCPWD_REJECT: 32929088Smarkm if (cnt > 0) { 33029088Smarkm printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n", 33129088Smarkm cnt, data); 33229088Smarkm } else 33329088Smarkm printf("[ RSA_ENCPWD refuses authentication ]\r\n"); 33429088Smarkm auth_send_retry(); 33529088Smarkm return; 33629088Smarkm case RSA_ENCPWD_ACCEPT: 33729088Smarkm printf("[ RSA_ENCPWD accepts you ]\n"); 33829088Smarkm auth_finished(ap, AUTH_USER); 33929088Smarkm return; 34029088Smarkm case RSA_ENCPWD_CHALLENGEKEY: 34129088Smarkm /* 34229088Smarkm * Verify that the response to the challenge is correct. 34329088Smarkm */ 34429088Smarkm 34529088Smarkm memmove((void *)chalkey, (void *)data, cnt); 34629088Smarkm ptr = (char *) &chalkey[0]; 34729088Smarkm ptr += DecodeHeaderLength(chalkey); 34829088Smarkm if (*ptr != 0x04) { 34929088Smarkm return; 35029088Smarkm } 35129088Smarkm *ptr++; 35229088Smarkm challenge_len = DecodeValueLength(ptr); 35329088Smarkm ptr += NumEncodeLengthOctets(challenge_len); 35429088Smarkm memmove(challenge, ptr, challenge_len); 35529088Smarkm ptr += challenge_len; 35629088Smarkm if (*ptr != 0x04) { 35729088Smarkm return; 35829088Smarkm } 35929088Smarkm *ptr++; 36029088Smarkm pubkey_len = DecodeValueLength(ptr); 36129088Smarkm ptr += NumEncodeLengthOctets(pubkey_len); 36229088Smarkm memmove(pubkey, ptr, pubkey_len); 36329088Smarkm memset(user_passwd, 0, sizeof(user_passwd)); 36429088Smarkm local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); 36529088Smarkm UserPassword = user_passwd; 36629088Smarkm Challenge = challenge; 36729088Smarkm r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey); 36829088Smarkm if (r < 0) { 36929088Smarkm token.length = 1; 37029088Smarkm } 37129088Smarkm 37229088Smarkm if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) { 37329088Smarkm return; 37429088Smarkm } 37529088Smarkm 37629088Smarkm break; 37729088Smarkm 37829088Smarkm default: 37929088Smarkm return; 38029088Smarkm } 38129088Smarkm} 38229088Smarkm 38329088Smarkm int 38429088Smarkmrsaencpwd_status(ap, name, level) 38529088Smarkm Authenticator *ap; 38629088Smarkm char *name; 38729088Smarkm int level; 38829088Smarkm{ 38929088Smarkm 39029088Smarkm if (level < AUTH_USER) 39129088Smarkm return(level); 39229088Smarkm 39329088Smarkm if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) { 39429088Smarkm strcpy(name, UserNameRequested); 39529088Smarkm return(AUTH_VALID); 39629088Smarkm } else { 39729088Smarkm return(AUTH_USER); 39829088Smarkm } 39929088Smarkm} 40029088Smarkm 40129088Smarkm#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 40229088Smarkm#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 40329088Smarkm 40429088Smarkm void 40529088Smarkmrsaencpwd_printsub(data, cnt, buf, buflen) 40629088Smarkm unsigned char *data, *buf; 40729088Smarkm int cnt, buflen; 40829088Smarkm{ 40929088Smarkm char lbuf[32]; 41029088Smarkm register int i; 41129088Smarkm 41229088Smarkm buf[buflen-1] = '\0'; /* make sure its NULL terminated */ 41329088Smarkm buflen -= 1; 41429088Smarkm 41529088Smarkm switch(data[3]) { 41629088Smarkm case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */ 41729088Smarkm strncpy((char *)buf, " REJECT ", buflen); 41829088Smarkm goto common; 41929088Smarkm 42029088Smarkm case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */ 42129088Smarkm strncpy((char *)buf, " ACCEPT ", buflen); 42229088Smarkm common: 42329088Smarkm BUMP(buf, buflen); 42429088Smarkm if (cnt <= 4) 42529088Smarkm break; 42629088Smarkm ADDC(buf, buflen, '"'); 42729088Smarkm for (i = 4; i < cnt; i++) 42829088Smarkm ADDC(buf, buflen, data[i]); 42929088Smarkm ADDC(buf, buflen, '"'); 43029088Smarkm ADDC(buf, buflen, '\0'); 43129088Smarkm break; 43229088Smarkm 43329088Smarkm case RSA_ENCPWD_AUTH: /* Authentication data follows */ 43429088Smarkm strncpy((char *)buf, " AUTH", buflen); 43529088Smarkm goto common2; 43629088Smarkm 43729088Smarkm case RSA_ENCPWD_CHALLENGEKEY: 43829088Smarkm strncpy((char *)buf, " CHALLENGEKEY", buflen); 43929088Smarkm goto common2; 44029088Smarkm 44129088Smarkm default: 44229088Smarkm sprintf(lbuf, " %d (unknown)", data[3]); 44329088Smarkm strncpy((char *)buf, lbuf, buflen); 44429088Smarkm common2: 44529088Smarkm BUMP(buf, buflen); 44629088Smarkm for (i = 4; i < cnt; i++) { 44729088Smarkm sprintf(lbuf, " %d", data[i]); 44829088Smarkm strncpy((char *)buf, lbuf, buflen); 44929088Smarkm BUMP(buf, buflen); 45029088Smarkm } 45129088Smarkm break; 45229088Smarkm } 45329088Smarkm} 45429088Smarkm 45529088Smarkmint rsaencpwd_passwdok(name, passwd) 45629088Smarkmchar *name, *passwd; 45729088Smarkm{ 45829088Smarkm char *crypt(); 45929088Smarkm char *salt, *p; 46029088Smarkm struct passwd *pwd; 46129088Smarkm int passwdok_status = 0; 46229088Smarkm 46329088Smarkm if (pwd = getpwnam(name)) 46429088Smarkm salt = pwd->pw_passwd; 46529088Smarkm else salt = "xx"; 46629088Smarkm 46729088Smarkm p = crypt(passwd, salt); 46829088Smarkm 46929088Smarkm if (pwd && !strcmp(p, pwd->pw_passwd)) { 47029088Smarkm passwdok_status = 1; 47129088Smarkm } else passwdok_status = 0; 47229088Smarkm return(passwdok_status); 47329088Smarkm} 47429088Smarkm 47529088Smarkm#endif 476