PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/crypto/telnet/libtelnet/rsaencpwd.c

https://repo.or.cz/dragonfly/vkernel-mp.git
C | 470 lines | 331 code | 52 blank | 87 comment | 55 complexity | 6b6ac24b9e6cfe4168047dab919f0548 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, Unlicense, BSD-3-Clause, ISC, GPL-2.0, AGPL-1.0
  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. * @(#)rsaencpwd.c 8.3 (Berkeley) 5/30/95
  34. * $FreeBSD: src/crypto/telnet/libtelnet/rsaencpwd.c,v 1.1.1.1.8.1 2002/04/13 10:59:07 markm Exp $
  35. * $DragonFly: src/crypto/telnet/libtelnet/rsaencpwd.c,v 1.2 2003/06/17 06:24:37 dillon Exp $
  36. */
  37. #ifdef RSA_ENCPWD
  38. /*
  39. * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
  40. * ALL RIGHTS RESERVED
  41. *
  42. * "Digital Equipment Corporation authorizes the reproduction,
  43. * distribution and modification of this software subject to the following
  44. * restrictions:
  45. *
  46. * 1. Any partial or whole copy of this software, or any modification
  47. * thereof, must include this copyright notice in its entirety.
  48. *
  49. * 2. This software is supplied "as is" with no warranty of any kind,
  50. * expressed or implied, for any purpose, including any warranty of fitness
  51. * or merchantibility. DIGITAL assumes no responsibility for the use or
  52. * reliability of this software, nor promises to provide any form of
  53. * support for it on any basis.
  54. *
  55. * 3. Distribution of this software is authorized only if no profit or
  56. * remuneration of any kind is received in exchange for such distribution.
  57. *
  58. * 4. This software produces public key authentication certificates
  59. * bearing an expiration date established by DIGITAL and RSA Data
  60. * Security, Inc. It may cease to generate certificates after the expiration
  61. * date. Any modification of this software that changes or defeats
  62. * the expiration date or its effect is unauthorized.
  63. *
  64. * 5. Software that will renew or extend the expiration date of
  65. * authentication certificates produced by this software may be obtained
  66. * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
  67. * 94065, (415)595-8782, or from DIGITAL"
  68. *
  69. */
  70. #include <sys/types.h>
  71. #include <arpa/telnet.h>
  72. #include <pwd.h>
  73. #include <stdio.h>
  74. #include <stdlib.h>
  75. #include <string.h>
  76. #include "encrypt.h"
  77. #include "auth.h"
  78. #include "misc.h"
  79. #include "cdc.h"
  80. extern auth_debug_mode;
  81. static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  82. AUTHTYPE_RSA_ENCPWD, };
  83. static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
  84. TELQUAL_NAME, };
  85. #define RSA_ENCPWD_AUTH 0 /* Authentication data follows */
  86. #define RSA_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
  87. #define RSA_ENCPWD_ACCEPT 2 /* Accepted */
  88. #define RSA_ENCPWD_CHALLENGEKEY 3 /* Challenge and public key */
  89. #define NAME_SZ 40
  90. #define CHAL_SZ 20
  91. #define PWD_SZ 40
  92. static KTEXT_ST auth;
  93. static char name[NAME_SZ];
  94. static char user_passwd[PWD_SZ];
  95. static char key_file[2*NAME_SZ];
  96. static char lhostname[NAME_SZ];
  97. static char challenge[CHAL_SZ];
  98. static int challenge_len;
  99. static int
  100. Data(ap, type, d, c)
  101. Authenticator *ap;
  102. int type;
  103. void *d;
  104. int c;
  105. {
  106. unsigned char *p = str_data + 4;
  107. unsigned char *cd = (unsigned char *)d;
  108. if (c == -1)
  109. c = strlen((char *)cd);
  110. if (0) {
  111. printf("%s:%d: [%d] (%d)",
  112. str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
  113. str_data[3],
  114. type, c);
  115. printd(d, c);
  116. printf("\r\n");
  117. }
  118. *p++ = ap->type;
  119. *p++ = ap->way;
  120. if (type != NULL) *p++ = type;
  121. while (c-- > 0) {
  122. if ((*p++ = *cd++) == IAC)
  123. *p++ = IAC;
  124. }
  125. *p++ = IAC;
  126. *p++ = SE;
  127. if (str_data[3] == TELQUAL_IS)
  128. printsub('>', &str_data[2], p - (&str_data[2]));
  129. return(net_write(str_data, p - str_data));
  130. }
  131. int
  132. rsaencpwd_init(ap, server)
  133. Authenticator *ap;
  134. int server;
  135. {
  136. char *cp;
  137. FILE *fp;
  138. if (server) {
  139. str_data[3] = TELQUAL_REPLY;
  140. memset(key_file, 0, sizeof(key_file));
  141. gethostname(lhostname, sizeof(lhostname));
  142. if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
  143. strcpy(key_file, "/etc/.");
  144. strcat(key_file, lhostname);
  145. strcat(key_file, "_privkey");
  146. if ((fp=fopen(key_file, "r"))==NULL) return(0);
  147. fclose(fp);
  148. } else {
  149. str_data[3] = TELQUAL_IS;
  150. }
  151. return(1);
  152. }
  153. int
  154. rsaencpwd_send(ap)
  155. Authenticator *ap;
  156. {
  157. printf("[ Trying RSAENCPWD ... ]\n");
  158. if (!UserNameRequested) {
  159. return(0);
  160. }
  161. if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
  162. return(0);
  163. }
  164. if (!Data(ap, NULL, (void *)NULL, 0)) {
  165. return(0);
  166. }
  167. return(1);
  168. }
  169. void
  170. rsaencpwd_is(ap, data, cnt)
  171. Authenticator *ap;
  172. unsigned char *data;
  173. int cnt;
  174. {
  175. Session_Key skey;
  176. Block datablock;
  177. char r_passwd[PWD_SZ], r_user[NAME_SZ];
  178. char *cp, key[160];
  179. char chalkey[160], *ptr;
  180. FILE *fp;
  181. int r, i, j, chalkey_len, len;
  182. time_t now;
  183. cnt--;
  184. switch (*data++) {
  185. case RSA_ENCPWD_AUTH:
  186. memmove((void *)auth.dat, (void *)data, auth.length = cnt);
  187. if ((fp=fopen(key_file, "r"))==NULL) {
  188. Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
  189. auth_finished(ap, AUTH_REJECT);
  190. return;
  191. }
  192. /*
  193. * get privkey
  194. */
  195. fscanf(fp, "%x;", &len);
  196. for (i=0;i<len;i++) {
  197. j = getc(fp); key[i]=j;
  198. }
  199. fclose(fp);
  200. r = accept_rsa_encpwd(&auth, key, challenge,
  201. challenge_len, r_passwd);
  202. if (r < 0) {
  203. Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
  204. auth_finished(ap, AUTH_REJECT);
  205. return;
  206. }
  207. auth_encrypt_userpwd(r_passwd);
  208. if (rsaencpwd_passwdok(UserNameRequested, UserPassword) == 0) {
  209. /*
  210. * illegal username and password
  211. */
  212. Data(ap, RSA_ENCPWD_REJECT, (void *)"Illegal password", -1);
  213. auth_finished(ap, AUTH_REJECT);
  214. return;
  215. }
  216. Data(ap, RSA_ENCPWD_ACCEPT, (void *)0, 0);
  217. auth_finished(ap, AUTH_USER);
  218. break;
  219. case IAC:
  220. /*
  221. * If we are doing mutual authentication, get set up to send
  222. * the challenge, and verify it when the response comes back.
  223. */
  224. if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
  225. register int i;
  226. time(&now);
  227. if ((now % 2) == 0) {
  228. sprintf(challenge, "%x", now);
  229. challenge_len = strlen(challenge);
  230. } else {
  231. strcpy(challenge, "randchal");
  232. challenge_len = 8;
  233. }
  234. if ((fp=fopen(key_file, "r"))==NULL) {
  235. Data(ap, RSA_ENCPWD_REJECT, (void *)"Auth failed", -1);
  236. auth_finished(ap, AUTH_REJECT);
  237. return;
  238. }
  239. /*
  240. * skip privkey
  241. */
  242. fscanf(fp, "%x;", &len);
  243. for (i=0;i<len;i++) {
  244. j = getc(fp);
  245. }
  246. /*
  247. * get pubkey
  248. */
  249. fscanf(fp, "%x;", &len);
  250. for (i=0;i<len;i++) {
  251. j = getc(fp); key[i]=j;
  252. }
  253. fclose(fp);
  254. chalkey[0] = 0x30;
  255. ptr = (char *) &chalkey[1];
  256. chalkey_len = 1+NumEncodeLengthOctets(i)+i+1+NumEncodeLengthOctets(challenge_len)+challenge_len;
  257. EncodeLength(ptr, chalkey_len);
  258. ptr +=NumEncodeLengthOctets(chalkey_len);
  259. *ptr++ = 0x04; /* OCTET STRING */
  260. *ptr++ = challenge_len;
  261. memmove(ptr, challenge, challenge_len);
  262. ptr += challenge_len;
  263. *ptr++ = 0x04; /* OCTET STRING */
  264. EncodeLength(ptr, i);
  265. ptr += NumEncodeLengthOctets(i);
  266. memmove(ptr, key, i);
  267. chalkey_len = 1+NumEncodeLengthOctets(chalkey_len)+chalkey_len;
  268. Data(ap, RSA_ENCPWD_CHALLENGEKEY, (void *)chalkey, chalkey_len);
  269. }
  270. break;
  271. default:
  272. Data(ap, RSA_ENCPWD_REJECT, 0, 0);
  273. break;
  274. }
  275. }
  276. void
  277. rsaencpwd_reply(ap, data, cnt)
  278. Authenticator *ap;
  279. unsigned char *data;
  280. int cnt;
  281. {
  282. Session_Key skey;
  283. KTEXT_ST token;
  284. Block enckey;
  285. int r, pubkey_len;
  286. char randchal[CHAL_SZ], *cp;
  287. char chalkey[160], pubkey[128], *ptr;
  288. if (cnt-- < 1)
  289. return;
  290. switch (*data++) {
  291. case RSA_ENCPWD_REJECT:
  292. if (cnt > 0) {
  293. printf("[ RSA_ENCPWD refuses authentication because %.*s ]\r\n",
  294. cnt, data);
  295. } else
  296. printf("[ RSA_ENCPWD refuses authentication ]\r\n");
  297. auth_send_retry();
  298. return;
  299. case RSA_ENCPWD_ACCEPT:
  300. printf("[ RSA_ENCPWD accepts you ]\n");
  301. auth_finished(ap, AUTH_USER);
  302. return;
  303. case RSA_ENCPWD_CHALLENGEKEY:
  304. /*
  305. * Verify that the response to the challenge is correct.
  306. */
  307. memmove((void *)chalkey, (void *)data, cnt);
  308. ptr = (char *) &chalkey[0];
  309. ptr += DecodeHeaderLength(chalkey);
  310. if (*ptr != 0x04) {
  311. return;
  312. }
  313. *ptr++;
  314. challenge_len = DecodeValueLength(ptr);
  315. ptr += NumEncodeLengthOctets(challenge_len);
  316. memmove(challenge, ptr, challenge_len);
  317. ptr += challenge_len;
  318. if (*ptr != 0x04) {
  319. return;
  320. }
  321. *ptr++;
  322. pubkey_len = DecodeValueLength(ptr);
  323. ptr += NumEncodeLengthOctets(pubkey_len);
  324. memmove(pubkey, ptr, pubkey_len);
  325. memset(user_passwd, 0, sizeof(user_passwd));
  326. local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
  327. UserPassword = user_passwd;
  328. Challenge = challenge;
  329. r = init_rsa_encpwd(&token, user_passwd, challenge, challenge_len, pubkey);
  330. if (r < 0) {
  331. token.length = 1;
  332. }
  333. if (!Data(ap, RSA_ENCPWD_AUTH, (void *)token.dat, token.length)) {
  334. return;
  335. }
  336. break;
  337. default:
  338. return;
  339. }
  340. }
  341. int
  342. rsaencpwd_status(ap, name, level)
  343. Authenticator *ap;
  344. char *name;
  345. int level;
  346. {
  347. if (level < AUTH_USER)
  348. return(level);
  349. if (UserNameRequested && rsaencpwd_passwdok(UserNameRequested, UserPassword)) {
  350. strcpy(name, UserNameRequested);
  351. return(AUTH_VALID);
  352. } else {
  353. return(AUTH_USER);
  354. }
  355. }
  356. #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
  357. #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
  358. void
  359. rsaencpwd_printsub(data, cnt, buf, buflen)
  360. unsigned char *data, *buf;
  361. int cnt, buflen;
  362. {
  363. char lbuf[32];
  364. register int i;
  365. buf[buflen-1] = '\0'; /* make sure its NULL terminated */
  366. buflen -= 1;
  367. switch(data[3]) {
  368. case RSA_ENCPWD_REJECT: /* Rejected (reason might follow) */
  369. strncpy((char *)buf, " REJECT ", buflen);
  370. goto common;
  371. case RSA_ENCPWD_ACCEPT: /* Accepted (name might follow) */
  372. strncpy((char *)buf, " ACCEPT ", buflen);
  373. common:
  374. BUMP(buf, buflen);
  375. if (cnt <= 4)
  376. break;
  377. ADDC(buf, buflen, '"');
  378. for (i = 4; i < cnt; i++)
  379. ADDC(buf, buflen, data[i]);
  380. ADDC(buf, buflen, '"');
  381. ADDC(buf, buflen, '\0');
  382. break;
  383. case RSA_ENCPWD_AUTH: /* Authentication data follows */
  384. strncpy((char *)buf, " AUTH", buflen);
  385. goto common2;
  386. case RSA_ENCPWD_CHALLENGEKEY:
  387. strncpy((char *)buf, " CHALLENGEKEY", buflen);
  388. goto common2;
  389. default:
  390. sprintf(lbuf, " %d (unknown)", data[3]);
  391. strncpy((char *)buf, lbuf, buflen);
  392. common2:
  393. BUMP(buf, buflen);
  394. for (i = 4; i < cnt; i++) {
  395. sprintf(lbuf, " %d", data[i]);
  396. strncpy((char *)buf, lbuf, buflen);
  397. BUMP(buf, buflen);
  398. }
  399. break;
  400. }
  401. }
  402. int rsaencpwd_passwdok(name, passwd)
  403. char *name, *passwd;
  404. {
  405. char *crypt();
  406. char *salt, *p;
  407. struct passwd *pwd;
  408. int passwdok_status = 0;
  409. if (pwd = getpwnam(name))
  410. salt = pwd->pw_passwd;
  411. else salt = "xx";
  412. p = crypt(passwd, salt);
  413. if (pwd && !strcmp(p, pwd->pw_passwd)) {
  414. passwdok_status = 1;
  415. } else passwdok_status = 0;
  416. return(passwdok_status);
  417. }
  418. #endif