157416Smarkm/*- 257416Smarkm * Copyright (c) 1992, 1993 357416Smarkm * The Regents of the University of California. All rights reserved. 457416Smarkm * 557416Smarkm * Redistribution and use in source and binary forms, with or without 657416Smarkm * modification, are permitted provided that the following conditions 757416Smarkm * are met: 857416Smarkm * 1. Redistributions of source code must retain the above copyright 957416Smarkm * notice, this list of conditions and the following disclaimer. 1057416Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1157416Smarkm * notice, this list of conditions and the following disclaimer in the 1257416Smarkm * documentation and/or other materials provided with the distribution. 1357416Smarkm * 3. All advertising materials mentioning features or use of this software 1457416Smarkm * must display the following acknowledgement: 1557416Smarkm * This product includes software developed by the University of 1657416Smarkm * California, Berkeley and its contributors. 1757416Smarkm * 4. Neither the name of the University nor the names of its contributors 1857416Smarkm * may be used to endorse or promote products derived from this software 1957416Smarkm * without specific prior written permission. 2057416Smarkm * 2157416Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2257416Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2357416Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2457416Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2557416Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2657416Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2757416Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2857416Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2957416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3057416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3157416Smarkm * SUCH DAMAGE. 3257416Smarkm */ 3357416Smarkm 3457416Smarkm#include <config.h> 3557416Smarkm 36233294SstasRCSID("$Id$"); 3757416Smarkm 3857416Smarkm#ifdef RSA_ENCPWD 3957416Smarkm/* 4057416Smarkm * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION 4157416Smarkm * ALL RIGHTS RESERVED 4257416Smarkm * 4357416Smarkm * "Digital Equipment Corporation authorizes the reproduction, 4457416Smarkm * distribution and modification of this software subject to the following 4557416Smarkm * restrictions: 4657416Smarkm * 4757416Smarkm * 1. Any partial or whole copy of this software, or any modification 4857416Smarkm * thereof, must include this copyright notice in its entirety. 4957416Smarkm * 5057416Smarkm * 2. This software is supplied "as is" with no warranty of any kind, 5157416Smarkm * expressed or implied, for any purpose, including any warranty of fitness 5257416Smarkm * or merchantibility. DIGITAL assumes no responsibility for the use or 5357416Smarkm * reliability of this software, nor promises to provide any form of 5457416Smarkm * support for it on any basis. 5557416Smarkm * 5657416Smarkm * 3. Distribution of this software is authorized only if no profit or 5757416Smarkm * remuneration of any kind is received in exchange for such distribution. 5857416Smarkm * 5957416Smarkm * 4. This software produces public key authentication certificates 6057416Smarkm * bearing an expiration date established by DIGITAL and RSA Data 6157416Smarkm * Security, Inc. It may cease to generate certificates after the expiration 6257416Smarkm * date. Any modification of this software that changes or defeats 6357416Smarkm * the expiration date or its effect is unauthorized. 6457416Smarkm * 6557416Smarkm * 5. Software that will renew or extend the expiration date of 6657416Smarkm * authentication certificates produced by this software may be obtained 6757416Smarkm * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA 6857416Smarkm * 94065, (415)595-8782, or from DIGITAL" 6957416Smarkm * 7057416Smarkm */ 7157416Smarkm 7257416Smarkm#include <sys/types.h> 7357416Smarkm#ifdef HAVE_ARPA_TELNET_H 7457416Smarkm#include <arpa/telnet.h> 7557416Smarkm#endif 7657416Smarkm#include <pwd.h> 7757416Smarkm#include <stdio.h> 7857416Smarkm 7957416Smarkm#include <stdlib.h> 8057416Smarkm#include <string.h> 8157416Smarkm#ifdef SOCKS 8257416Smarkm#include <socks.h> 8357416Smarkm#endif 8457416Smarkm 8557416Smarkm#include "encrypt.h" 8657416Smarkm#include "auth.h" 8757416Smarkm#include "misc.h" 8857416Smarkm#include "cdc.h" 8957416Smarkm 9057416Smarkmextern auth_debug_mode; 9157416Smarkm 9257416Smarkmstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0, 9357416Smarkm AUTHTYPE_RSA_ENCPWD, }; 9457416Smarkmstatic unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 9557416Smarkm TELQUAL_NAME, }; 9657416Smarkm 9757416Smarkm#define RSA_ENCPWD_AUTH 0 /* Authentication data follows */ 9857416Smarkm#define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */ 9957416Smarkm#define RSA_ENCPWD_ACCEPT 2 /* Accepted */ 10057416Smarkm#define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */ 10157416Smarkm 10257416Smarkm#define NAME_SZ 40 10357416Smarkm#define CHAL_SZ 20 10457416Smarkm#define PWD_SZ 40 10557416Smarkm 10657416Smarkmstatic KTEXT_ST auth; 10757416Smarkmstatic char name[NAME_SZ]; 10857416Smarkmstatic char user_passwd[PWD_SZ]; 10957416Smarkmstatic char key_file[2*NAME_SZ]; 11057416Smarkmstatic char lhostname[NAME_SZ]; 11157416Smarkmstatic char challenge[CHAL_SZ]; 11257416Smarkmstatic int challenge_len; 11357416Smarkm 11457416Smarkm static int 11557416SmarkmData(ap, type, d, c) 11657416Smarkm Authenticator *ap; 11757416Smarkm int type; 11857416Smarkm void *d; 11957416Smarkm int c; 12057416Smarkm{ 12157416Smarkm unsigned char *p = str_data + 4; 12257416Smarkm unsigned char *cd = (unsigned char *)d; 12357416Smarkm 12457416Smarkm if (c == -1) 12557416Smarkm c = strlen((char *)cd); 12657416Smarkm 12757416Smarkm if (0) { 12857416Smarkm printf("%s:%d: [%d] (%d)", 12957416Smarkm str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY", 13057416Smarkm str_data[3], 13157416Smarkm type, c); 13257416Smarkm printd(d, c); 13357416Smarkm printf("\r\n"); 13457416Smarkm } 13557416Smarkm *p++ = ap->type; 13657416Smarkm *p++ = ap->way; 13757416Smarkm if (type != NULL) *p++ = type; 13857416Smarkm while (c-- > 0) { 13957416Smarkm if ((*p++ = *cd++) == IAC) 14057416Smarkm *p++ = IAC; 14157416Smarkm } 14257416Smarkm *p++ = IAC; 14357416Smarkm *p++ = SE; 14457416Smarkm if (str_data[3] == TELQUAL_IS) 14557416Smarkm printsub('>', &str_data[2], p - (&str_data[2])); 14657416Smarkm return(telnet_net_write(str_data, p - str_data)); 14757416Smarkm} 14857416Smarkm 14957416Smarkm int 15057416Smarkmrsaencpwd_init(ap, server) 15157416Smarkm Authenticator *ap; 15257416Smarkm int server; 15357416Smarkm{ 15457416Smarkm char *cp; 15557416Smarkm FILE *fp; 15657416Smarkm 15757416Smarkm if (server) { 15857416Smarkm str_data[3] = TELQUAL_REPLY; 15957416Smarkm memset(key_file, 0, sizeof(key_file)); 16057416Smarkm gethostname(lhostname, sizeof(lhostname)); 16157416Smarkm if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0'; 16257416Smarkm snprintf(key_file, sizeof(key_file), 163102644Snectar SYSCONFDIR "/.%s_privkey", lhostname); 16457416Smarkm if ((fp=fopen(key_file, "r"))==NULL) return(0); 16557416Smarkm fclose(fp); 16657416Smarkm } else { 16757416Smarkm str_data[3] = TELQUAL_IS; 16857416Smarkm } 16957416Smarkm return(1); 17057416Smarkm} 17157416Smarkm 17257416Smarkm int 17357416Smarkmrsaencpwd_send(ap) 17457416Smarkm Authenticator *ap; 17557416Smarkm{ 17657416Smarkm 17757416Smarkm printf("[ Trying RSAENCPWD ... ]\r\n"); 17857416Smarkm if (!UserNameRequested) { 17957416Smarkm return(0); 18057416Smarkm } 18157416Smarkm if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) { 18257416Smarkm return(0); 18357416Smarkm } 18457416Smarkm if (!Data(ap, NULL, NULL, 0)) { 18557416Smarkm return(0); 18657416Smarkm } 18757416Smarkm 18857416Smarkm 18957416Smarkm return(1); 19057416Smarkm} 19157416Smarkm 19257416Smarkm void 19357416Smarkmrsaencpwd_is(ap, data, cnt) 19457416Smarkm Authenticator *ap; 19557416Smarkm unsigned char *data; 19657416Smarkm int cnt; 19757416Smarkm{ 19857416Smarkm Session_Key skey; 19957416Smarkm des_cblock datablock; 20057416Smarkm char r_passwd[PWD_SZ], r_user[NAME_SZ]; 20157416Smarkm char *cp, key[160]; 20257416Smarkm char chalkey[160], *ptr; 20357416Smarkm FILE *fp; 20457416Smarkm int r, i, j, chalkey_len, len; 20557416Smarkm time_t now; 20657416Smarkm 20757416Smarkm cnt--; 20857416Smarkm switch (*data++) { 20957416Smarkm case RSA_ENCPWD_AUTH: 21057416Smarkm memmove(auth.dat, data, auth.length = cnt); 21157416Smarkm 21257416Smarkm if ((fp=fopen(key_file, "r"))==NULL) { 21357416Smarkm Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1); 21457416Smarkm auth_finished(ap, AUTH_REJECT); 21557416Smarkm return; 21657416Smarkm } 21757416Smarkm /* 21857416Smarkm * get privkey 21957416Smarkm */ 22057416Smarkm fscanf(fp, "%x;", &len); 22157416Smarkm for (i=0;i<len;i++) { 22257416Smarkm j = getc(fp); key[i]=j; 22357416Smarkm } 22457416Smarkm fclose(fp); 22557416Smarkm 22657416Smarkm r = accept_rsa_encpwd(&auth, key, challenge, 22757416Smarkm challenge_len, r_passwd); 22857416Smarkm if (r < 0) { 22957416Smarkm Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1); 23057416Smarkm auth_finished(ap, AUTH_REJECT); 23157416Smarkm return; 23257416Smarkm } 23357416Smarkm auth_encrypt_userpwd(r_passwd); 23457416Smarkm if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) { 23557416Smarkm /* 23657416Smarkm * illegal username and password 23757416Smarkm */ 23857416Smarkm Data(ap, RSA_ENCPWD_REJECT, "Illegal password", -1); 23957416Smarkm auth_finished(ap, AUTH_REJECT); 24057416Smarkm return; 24157416Smarkm } 24257416Smarkm 24357416Smarkm Data(ap, RSA_ENCPWD_ACCEPT, 0, 0); 24457416Smarkm auth_finished(ap, AUTH_USER); 24557416Smarkm break; 24657416Smarkm 24757416Smarkm 24857416Smarkm case IAC: 24957416Smarkm 25057416Smarkm /* 25157416Smarkm * If we are doing mutual authentication, get set up to send 25257416Smarkm * the challenge, and verify it when the response comes back. 25357416Smarkm */ 25457416Smarkm if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) { 25557416Smarkm int i; 25657416Smarkm 25757416Smarkm 25857416Smarkm time(&now); 25957416Smarkm if ((now % 2) == 0) { 26057416Smarkm snprintf(challenge, sizeof(challenge), "%x", now); 26157416Smarkm challenge_len = strlen(challenge); 26257416Smarkm } else { 26357416Smarkm strlcpy(challenge, "randchal", sizeof(challenge)); 26457416Smarkm challenge_len = 8; 26557416Smarkm } 26657416Smarkm 26757416Smarkm if ((fp=fopen(key_file, "r"))==NULL) { 26857416Smarkm Data(ap, RSA_ENCPWD_REJECT, "Auth failed", -1); 26957416Smarkm auth_finished(ap, AUTH_REJECT); 27057416Smarkm return; 27157416Smarkm } 27257416Smarkm /* 27357416Smarkm * skip privkey 27457416Smarkm */ 27557416Smarkm fscanf(fp, "%x;", &len); 27657416Smarkm for (i=0;i<len;i++) { 27757416Smarkm j = getc(fp); 27857416Smarkm } 27957416Smarkm /* 28057416Smarkm * get pubkey 28157416Smarkm */ 28257416Smarkm fscanf(fp, "%x;", &len); 28357416Smarkm for (i=0;i<len;i++) { 28457416Smarkm j = getc(fp); key[i]=j; 28557416Smarkm } 28657416Smarkm fclose(fp); 28757416Smarkm chalkey[0] = 0x30; 28857416Smarkm ptr = (char *) &chalkey[1]; 28957416Smarkm chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len; 29057416Smarkm EncodeLength(ptr, chalkey_len); 29157416Smarkm ptr +=NumEncodeLengthOctets(chalkey_len); 29257416Smarkm *ptr++ = 0x04; /* OCTET STRING */ 29357416Smarkm *ptr++ = challenge_len; 29457416Smarkm memmove(ptr, challenge, challenge_len); 29557416Smarkm ptr += challenge_len; 29657416Smarkm *ptr++ = 0x04; /* OCTET STRING */ 29757416Smarkm EncodeLength(ptr, i); 29857416Smarkm ptr += NumEncodeLengthOctets(i); 29957416Smarkm memmove(ptr, key, i); 30057416Smarkm chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len; 30157416Smarkm Data(ap, RSA_ENCPWD_CHALLENGEKEY, chalkey, chalkey_len); 30257416Smarkm } 30357416Smarkm break; 30457416Smarkm 30557416Smarkm default: 30657416Smarkm Data(ap, RSA_ENCPWD_REJECT, 0, 0); 30757416Smarkm break; 30857416Smarkm } 30957416Smarkm} 31057416Smarkm 31157416Smarkm 31257416Smarkm void 31357416Smarkmrsaencpwd_reply(ap, data, cnt) 31457416Smarkm Authenticator *ap; 31557416Smarkm unsigned char *data; 31657416Smarkm int cnt; 31757416Smarkm{ 31857416Smarkm Session_Key skey; 31957416Smarkm KTEXT_ST token; 32057416Smarkm des_cblock enckey; 32157416Smarkm int r, pubkey_len; 32257416Smarkm char randchal[CHAL_SZ], *cp; 32357416Smarkm char chalkey[160], pubkey[128], *ptr; 32457416Smarkm 32557416Smarkm if (cnt-- < 1) 32657416Smarkm return; 32757416Smarkm switch (*data++) { 32857416Smarkm case RSA_ENCPWD_REJECT: 32957416Smarkm if (cnt > 0) { 33057416Smarkm printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n", 33157416Smarkm cnt, data); 33257416Smarkm } else 33357416Smarkm printf("[ RSA_ENCPWD refuses authentication ]\r\n"); 33457416Smarkm auth_send_retry(); 33557416Smarkm return; 33657416Smarkm case RSA_ENCPWD_ACCEPT: 33757416Smarkm printf("[ RSA_ENCPWD accepts you ]\r\n"); 33857416Smarkm auth_finished(ap, AUTH_USER); 33957416Smarkm return; 34057416Smarkm case RSA_ENCPWD_CHALLENGEKEY: 34157416Smarkm /* 34257416Smarkm * Verify that the response to the challenge is correct. 34357416Smarkm */ 34457416Smarkm 34557416Smarkm memmove(chalkey, data, cnt); 34657416Smarkm ptr = (char *) &chalkey[0]; 34757416Smarkm ptr += DecodeHeaderLength(chalkey); 34857416Smarkm if (*ptr != 0x04) { 34957416Smarkm return; 35057416Smarkm } 35157416Smarkm *ptr++; 35257416Smarkm challenge_len = DecodeValueLength(ptr); 35357416Smarkm ptr += NumEncodeLengthOctets(challenge_len); 35457416Smarkm memmove(challenge, ptr, challenge_len); 35557416Smarkm ptr += challenge_len; 35657416Smarkm if (*ptr != 0x04) { 35757416Smarkm return; 35857416Smarkm } 35957416Smarkm *ptr++; 36057416Smarkm pubkey_len = DecodeValueLength(ptr); 36157416Smarkm ptr += NumEncodeLengthOctets(pubkey_len); 36257416Smarkm memmove(pubkey, ptr, pubkey_len); 36357416Smarkm memset(user_passwd, 0, sizeof(user_passwd)); 36457416Smarkm des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0); 36557416Smarkm UserPassword = user_passwd; 36657416Smarkm Challenge = challenge; 36757416Smarkm r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey); 36857416Smarkm if (r < 0) { 36957416Smarkm token.length = 1; 37057416Smarkm } 37157416Smarkm 37257416Smarkm if (!Data(ap, RSA_ENCPWD_AUTH, token.dat, token.length)) { 37357416Smarkm return; 37457416Smarkm } 37557416Smarkm 37657416Smarkm break; 37757416Smarkm 37857416Smarkm default: 37957416Smarkm return; 38057416Smarkm } 38157416Smarkm} 38257416Smarkm 38357416Smarkm int 38457416Smarkmrsaencpwd_status(ap, name, name_sz, level) 38557416Smarkm Authenticator *ap; 38657416Smarkm char *name; 38757416Smarkm size_t name_sz; 38857416Smarkm int level; 38957416Smarkm{ 39057416Smarkm 39157416Smarkm if (level < AUTH_USER) 39257416Smarkm return(level); 39357416Smarkm 39457416Smarkm if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) { 39557416Smarkm strlcpy(name, UserNameRequested, name_sz); 39657416Smarkm return(AUTH_VALID); 39757416Smarkm } else { 39857416Smarkm return(AUTH_USER); 39957416Smarkm } 40057416Smarkm} 40157416Smarkm 40257416Smarkm#define BUMP(buf, len) while (*(buf)) {++(buf), --(len);} 40357416Smarkm#define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);} 40457416Smarkm 40557416Smarkm void 406233294Sstasrsaencpwd_printsub(unsigned char *data, size_t cnt, 407233294Sstas unsigned char * buf, size_t buflen) 40857416Smarkm{ 409233294Sstas size_t i; 41057416Smarkm 411178825Sdfr buf[buflen-1] = '\0'; /* make sure it's NULL terminated */ 41257416Smarkm buflen -= 1; 41357416Smarkm 41457416Smarkm switch(data[3]) { 41557416Smarkm case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */ 41657416Smarkm strlcpy((char *)buf, " REJECT ", buflen); 41757416Smarkm goto common; 41857416Smarkm 41957416Smarkm case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */ 42057416Smarkm strlcpy((char *)buf, " ACCEPT ", buflen); 42157416Smarkm common: 42257416Smarkm BUMP(buf, buflen); 42357416Smarkm if (cnt <= 4) 42457416Smarkm break; 42557416Smarkm ADDC(buf, buflen, '"'); 42657416Smarkm for (i = 4; i < cnt; i++) 42757416Smarkm ADDC(buf, buflen, data[i]); 42857416Smarkm ADDC(buf, buflen, '"'); 42957416Smarkm ADDC(buf, buflen, '\0'); 43057416Smarkm break; 43157416Smarkm 43257416Smarkm case RSA_ENCPWD_AUTH: /* Authentication data follows */ 43357416Smarkm strlcpy((char *)buf, " AUTH", buflen); 43457416Smarkm goto common2; 43557416Smarkm 43657416Smarkm case RSA_ENCPWD_CHALLENGEKEY: 43757416Smarkm strlcpy((char *)buf, " CHALLENGEKEY", buflen); 43857416Smarkm goto common2; 43957416Smarkm 44057416Smarkm default: 44157416Smarkm snprintf(buf, buflen, " %d (unknown)", data[3]); 44257416Smarkm common2: 44357416Smarkm BUMP(buf, buflen); 44457416Smarkm for (i = 4; i < cnt; i++) { 44557416Smarkm snprintf(buf, buflen, " %d", data[i]); 44657416Smarkm BUMP(buf, buflen); 44757416Smarkm } 44857416Smarkm break; 44957416Smarkm } 45057416Smarkm} 45157416Smarkm 45257416Smarkmint rsaencpwd_passwdok(name, passwd) 45357416Smarkmchar *name, *passwd; 45457416Smarkm{ 45557416Smarkm char *crypt(); 45657416Smarkm char *salt, *p; 45757416Smarkm struct passwd *pwd; 45857416Smarkm int passwdok_status = 0; 45957416Smarkm 46057416Smarkm if (pwd = k_getpwnam(name)) 46157416Smarkm salt = pwd->pw_passwd; 46257416Smarkm else salt = "xx"; 46357416Smarkm 46457416Smarkm p = crypt(passwd, salt); 46557416Smarkm 46657416Smarkm if (pwd && !strcmp(p, pwd->pw_passwd)) { 46757416Smarkm passwdok_status = 1; 46857416Smarkm } else passwdok_status = 0; 46957416Smarkm return(passwdok_status); 47057416Smarkm} 47157416Smarkm 47257416Smarkm#endif 47357416Smarkm 47457416Smarkm#ifdef notdef 47557416Smarkm 47657416Smarkmprkey(msg, key) 47757416Smarkm char *msg; 47857416Smarkm unsigned char *key; 47957416Smarkm{ 48057416Smarkm int i; 48157416Smarkm printf("%s:", msg); 48257416Smarkm for (i = 0; i < 8; i++) 48357416Smarkm printf(" %3d", key[i]); 48457416Smarkm printf("\r\n"); 48557416Smarkm} 48657416Smarkm#endif 487