/crypto/heimdal/appl/telnet/libtelnet/spx.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 589 lines · 431 code · 84 blank · 74 comment · 46 complexity · d91427c0f798639ccb7c4ee1ff2e00cd MD5 · raw file

  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. #include <config.h>
  34. RCSID("$Id$");
  35. #ifdef SPX
  36. /*
  37. * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
  38. * ALL RIGHTS RESERVED
  39. *
  40. * "Digital Equipment Corporation authorizes the reproduction,
  41. * distribution and modification of this software subject to the following
  42. * restrictions:
  43. *
  44. * 1. Any partial or whole copy of this software, or any modification
  45. * thereof, must include this copyright notice in its entirety.
  46. *
  47. * 2. This software is supplied "as is" with no warranty of any kind,
  48. * expressed or implied, for any purpose, including any warranty of fitness
  49. * or merchantibility. DIGITAL assumes no responsibility for the use or
  50. * reliability of this software, nor promises to provide any form of
  51. * support for it on any basis.
  52. *
  53. * 3. Distribution of this software is authorized only if no profit or
  54. * remuneration of any kind is received in exchange for such distribution.
  55. *
  56. * 4. This software produces public key authentication certificates
  57. * bearing an expiration date established by DIGITAL and RSA Data
  58. * Security, Inc. It may cease to generate certificates after the expiration
  59. * date. Any modification of this software that changes or defeats
  60. * the expiration date or its effect is unauthorized.
  61. *
  62. * 5. Software that will renew or extend the expiration date of
  63. * authentication certificates produced by this software may be obtained
  64. * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
  65. * 94065, (415)595-8782, or from DIGITAL"
  66. *
  67. */
  68. #ifdef HAVE_SYS_TYPES_H
  69. #include <sys/types.h>
  70. #endif
  71. #ifdef HAVE_ARPA_TELNET_H
  72. #include <arpa/telnet.h>
  73. #endif
  74. #include <stdio.h>
  75. #include "gssapi_defs.h"
  76. #include <stdlib.h>
  77. #include <string.h>
  78. #include <pwd.h>
  79. #ifdef SOCKS
  80. #include <socks.h>
  81. #endif
  82. #include "encrypt.h"
  83. #include "auth.h"
  84. #include "misc.h"
  85. extern auth_debug_mode;
  86. static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  87. AUTHTYPE_SPX, };
  88. static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
  89. TELQUAL_NAME, };
  90. #define SPX_AUTH 0 /* Authentication data follows */
  91. #define SPX_REJECT 1 /* Rejected (reason might follow) */
  92. #define SPX_ACCEPT 2 /* Accepted */
  93. static des_key_schedule sched;
  94. static des_cblock challenge = { 0 };
  95. /*******************************************************************/
  96. gss_OID_set actual_mechs;
  97. gss_OID actual_mech_type, output_name_type;
  98. int major_status, status, msg_ctx = 0, new_status;
  99. int req_flags = 0, ret_flags, lifetime_rec;
  100. gss_cred_id_t gss_cred_handle;
  101. gss_ctx_id_t actual_ctxhandle, context_handle;
  102. gss_buffer_desc output_token, input_token, input_name_buffer;
  103. gss_buffer_desc status_string;
  104. gss_name_t desired_targname, src_name;
  105. gss_channel_bindings input_chan_bindings;
  106. char lhostname[GSS_C_MAX_PRINTABLE_NAME];
  107. char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
  108. int to_addr=0, from_addr=0;
  109. char *address;
  110. gss_buffer_desc fullname_buffer;
  111. gss_OID fullname_type;
  112. gss_cred_id_t gss_delegated_cred_handle;
  113. /*******************************************************************/
  114. static int
  115. Data(ap, type, d, c)
  116. Authenticator *ap;
  117. int type;
  118. void *d;
  119. int c;
  120. {
  121. unsigned char *p = str_data + 4;
  122. unsigned char *cd = (unsigned char *)d;
  123. if (c == -1)
  124. c = strlen((char *)cd);
  125. if (0) {
  126. printf("%s:%d: [%d] (%d)",
  127. str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
  128. str_data[3],
  129. type, c);
  130. printd(d, c);
  131. printf("\r\n");
  132. }
  133. *p++ = ap->type;
  134. *p++ = ap->way;
  135. *p++ = type;
  136. while (c-- > 0) {
  137. if ((*p++ = *cd++) == IAC)
  138. *p++ = IAC;
  139. }
  140. *p++ = IAC;
  141. *p++ = SE;
  142. if (str_data[3] == TELQUAL_IS)
  143. printsub('>', &str_data[2], p - (&str_data[2]));
  144. return(telnet_net_write(str_data, p - str_data));
  145. }
  146. int
  147. spx_init(ap, server)
  148. Authenticator *ap;
  149. int server;
  150. {
  151. gss_cred_id_t tmp_cred_handle;
  152. if (server) {
  153. str_data[3] = TELQUAL_REPLY;
  154. gethostname(lhostname, sizeof(lhostname));
  155. snprintf (targ_printable, sizeof(targ_printable),
  156. "SERVICE:rcmd@%s", lhostname);
  157. input_name_buffer.length = strlen(targ_printable);
  158. input_name_buffer.value = targ_printable;
  159. major_status = gss_import_name(&status,
  160. &input_name_buffer,
  161. GSS_C_NULL_OID,
  162. &desired_targname);
  163. major_status = gss_acquire_cred(&status,
  164. desired_targname,
  165. 0,
  166. GSS_C_NULL_OID_SET,
  167. GSS_C_ACCEPT,
  168. &tmp_cred_handle,
  169. &actual_mechs,
  170. &lifetime_rec);
  171. if (major_status != GSS_S_COMPLETE) return(0);
  172. } else {
  173. str_data[3] = TELQUAL_IS;
  174. }
  175. return(1);
  176. }
  177. int
  178. spx_send(ap)
  179. Authenticator *ap;
  180. {
  181. des_cblock enckey;
  182. int r;
  183. gss_OID actual_mech_type, output_name_type;
  184. int msg_ctx = 0, new_status, status;
  185. int req_flags = 0, ret_flags, lifetime_rec, major_status;
  186. gss_buffer_desc output_token, input_token, input_name_buffer;
  187. gss_buffer_desc output_name_buffer, status_string;
  188. gss_name_t desired_targname;
  189. gss_channel_bindings input_chan_bindings;
  190. char targ_printable[GSS_C_MAX_PRINTABLE_NAME];
  191. int from_addr=0, to_addr=0, myhostlen, j;
  192. int deleg_flag=1, mutual_flag=0, replay_flag=0, seq_flag=0;
  193. char *address;
  194. printf("[ Trying SPX ... ]\r\n");
  195. snprintf (targ_printable, sizeof(targ_printable),
  196. "SERVICE:rcmd@%s", RemoteHostName);
  197. input_name_buffer.length = strlen(targ_printable);
  198. input_name_buffer.value = targ_printable;
  199. if (!UserNameRequested) {
  200. return(0);
  201. }
  202. major_status = gss_import_name(&status,
  203. &input_name_buffer,
  204. GSS_C_NULL_OID,
  205. &desired_targname);
  206. major_status = gss_display_name(&status,
  207. desired_targname,
  208. &output_name_buffer,
  209. &output_name_type);
  210. printf("target is '%.*s'\n", (int)output_name_buffer.length,
  211. (char*)output_name_buffer.value);
  212. fflush(stdout);
  213. major_status = gss_release_buffer(&status, &output_name_buffer);
  214. input_chan_bindings = (gss_channel_bindings)
  215. malloc(sizeof(gss_channel_bindings_desc));
  216. input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
  217. input_chan_bindings->initiator_address.length = 4;
  218. address = (char *) malloc(4);
  219. input_chan_bindings->initiator_address.value = (char *) address;
  220. address[0] = ((from_addr & 0xff000000) >> 24);
  221. address[1] = ((from_addr & 0xff0000) >> 16);
  222. address[2] = ((from_addr & 0xff00) >> 8);
  223. address[3] = (from_addr & 0xff);
  224. input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
  225. input_chan_bindings->acceptor_address.length = 4;
  226. address = (char *) malloc(4);
  227. input_chan_bindings->acceptor_address.value = (char *) address;
  228. address[0] = ((to_addr & 0xff000000) >> 24);
  229. address[1] = ((to_addr & 0xff0000) >> 16);
  230. address[2] = ((to_addr & 0xff00) >> 8);
  231. address[3] = (to_addr & 0xff);
  232. input_chan_bindings->application_data.length = 0;
  233. req_flags = 0;
  234. if (deleg_flag) req_flags = req_flags | 1;
  235. if (mutual_flag) req_flags = req_flags | 2;
  236. if (replay_flag) req_flags = req_flags | 4;
  237. if (seq_flag) req_flags = req_flags | 8;
  238. major_status = gss_init_sec_context(&status, /* minor status */
  239. GSS_C_NO_CREDENTIAL, /* cred handle */
  240. &actual_ctxhandle, /* ctx handle */
  241. desired_targname, /* target name */
  242. GSS_C_NULL_OID, /* mech type */
  243. req_flags, /* req flags */
  244. 0, /* time req */
  245. input_chan_bindings, /* chan binding */
  246. GSS_C_NO_BUFFER, /* input token */
  247. &actual_mech_type, /* actual mech */
  248. &output_token, /* output token */
  249. &ret_flags, /* ret flags */
  250. &lifetime_rec); /* time rec */
  251. if ((major_status != GSS_S_COMPLETE) &&
  252. (major_status != GSS_S_CONTINUE_NEEDED)) {
  253. gss_display_status(&new_status,
  254. status,
  255. GSS_C_MECH_CODE,
  256. GSS_C_NULL_OID,
  257. &msg_ctx,
  258. &status_string);
  259. printf("%.*s\n", (int)status_string.length,
  260. (char*)status_string.value);
  261. return(0);
  262. }
  263. if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
  264. return(0);
  265. }
  266. if (!Data(ap, SPX_AUTH, output_token.value, output_token.length)) {
  267. return(0);
  268. }
  269. return(1);
  270. }
  271. void
  272. spx_is(ap, data, cnt)
  273. Authenticator *ap;
  274. unsigned char *data;
  275. int cnt;
  276. {
  277. Session_Key skey;
  278. des_cblock datablock;
  279. int r;
  280. if (cnt-- < 1)
  281. return;
  282. switch (*data++) {
  283. case SPX_AUTH:
  284. input_token.length = cnt;
  285. input_token.value = (char *) data;
  286. gethostname(lhostname, sizeof(lhostname));
  287. snprintf(targ_printable, sizeof(targ_printable),
  288. "SERVICE:rcmd@%s", lhostname);
  289. input_name_buffer.length = strlen(targ_printable);
  290. input_name_buffer.value = targ_printable;
  291. major_status = gss_import_name(&status,
  292. &input_name_buffer,
  293. GSS_C_NULL_OID,
  294. &desired_targname);
  295. major_status = gss_acquire_cred(&status,
  296. desired_targname,
  297. 0,
  298. GSS_C_NULL_OID_SET,
  299. GSS_C_ACCEPT,
  300. &gss_cred_handle,
  301. &actual_mechs,
  302. &lifetime_rec);
  303. major_status = gss_release_name(&status, desired_targname);
  304. input_chan_bindings = (gss_channel_bindings)
  305. malloc(sizeof(gss_channel_bindings_desc));
  306. input_chan_bindings->initiator_addrtype = GSS_C_AF_INET;
  307. input_chan_bindings->initiator_address.length = 4;
  308. address = (char *) malloc(4);
  309. input_chan_bindings->initiator_address.value = (char *) address;
  310. address[0] = ((from_addr & 0xff000000) >> 24);
  311. address[1] = ((from_addr & 0xff0000) >> 16);
  312. address[2] = ((from_addr & 0xff00) >> 8);
  313. address[3] = (from_addr & 0xff);
  314. input_chan_bindings->acceptor_addrtype = GSS_C_AF_INET;
  315. input_chan_bindings->acceptor_address.length = 4;
  316. address = (char *) malloc(4);
  317. input_chan_bindings->acceptor_address.value = (char *) address;
  318. address[0] = ((to_addr & 0xff000000) >> 24);
  319. address[1] = ((to_addr & 0xff0000) >> 16);
  320. address[2] = ((to_addr & 0xff00) >> 8);
  321. address[3] = (to_addr & 0xff);
  322. input_chan_bindings->application_data.length = 0;
  323. major_status = gss_accept_sec_context(&status,
  324. &context_handle,
  325. gss_cred_handle,
  326. &input_token,
  327. input_chan_bindings,
  328. &src_name,
  329. &actual_mech_type,
  330. &output_token,
  331. &ret_flags,
  332. &lifetime_rec,
  333. &gss_delegated_cred_handle);
  334. if (major_status != GSS_S_COMPLETE) {
  335. major_status = gss_display_name(&status,
  336. src_name,
  337. &fullname_buffer,
  338. &fullname_type);
  339. Data(ap, SPX_REJECT, "auth failed", -1);
  340. auth_finished(ap, AUTH_REJECT);
  341. return;
  342. }
  343. major_status = gss_display_name(&status,
  344. src_name,
  345. &fullname_buffer,
  346. &fullname_type);
  347. Data(ap, SPX_ACCEPT, output_token.value, output_token.length);
  348. auth_finished(ap, AUTH_USER);
  349. break;
  350. default:
  351. Data(ap, SPX_REJECT, 0, 0);
  352. break;
  353. }
  354. }
  355. void
  356. spx_reply(ap, data, cnt)
  357. Authenticator *ap;
  358. unsigned char *data;
  359. int cnt;
  360. {
  361. Session_Key skey;
  362. if (cnt-- < 1)
  363. return;
  364. switch (*data++) {
  365. case SPX_REJECT:
  366. if (cnt > 0) {
  367. printf("[ SPX refuses authentication because %.*s ]\r\n",
  368. cnt, data);
  369. } else
  370. printf("[ SPX refuses authentication ]\r\n");
  371. auth_send_retry();
  372. return;
  373. case SPX_ACCEPT:
  374. printf("[ SPX accepts you ]\r\n");
  375. if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  376. /*
  377. * Send over the encrypted challenge.
  378. */
  379. input_token.value = (char *) data;
  380. input_token.length = cnt;
  381. major_status = gss_init_sec_context(&status, /* minor stat */
  382. GSS_C_NO_CREDENTIAL, /* cred handle */
  383. &actual_ctxhandle, /* ctx handle */
  384. desired_targname, /* target name */
  385. GSS_C_NULL_OID, /* mech type */
  386. req_flags, /* req flags */
  387. 0, /* time req */
  388. input_chan_bindings, /* chan binding */
  389. &input_token, /* input token */
  390. &actual_mech_type, /* actual mech */
  391. &output_token, /* output token */
  392. &ret_flags, /* ret flags */
  393. &lifetime_rec); /* time rec */
  394. if (major_status != GSS_S_COMPLETE) {
  395. gss_display_status(&new_status,
  396. status,
  397. GSS_C_MECH_CODE,
  398. GSS_C_NULL_OID,
  399. &msg_ctx,
  400. &status_string);
  401. printf("[ SPX mutual response fails ... '%.*s' ]\r\n",
  402. (int)status_string.length,
  403. (char*)status_string.value);
  404. auth_send_retry();
  405. return;
  406. }
  407. }
  408. auth_finished(ap, AUTH_USER);
  409. return;
  410. default:
  411. return;
  412. }
  413. }
  414. int
  415. spx_status(ap, name, name_sz, level)
  416. Authenticator *ap;
  417. char *name;
  418. size_t name_sz;
  419. int level;
  420. {
  421. gss_buffer_desc fullname_buffer, acl_file_buffer;
  422. gss_OID fullname_type;
  423. char acl_file[160], fullname[160];
  424. int major_status, status = 0;
  425. struct passwd *pwd;
  426. /*
  427. * hard code fullname to
  428. * "SPX:/C=US/O=Digital/OU=LKG/OU=Sphinx/OU=Users/CN=Kannan Alagappan"
  429. * and acl_file to "~kannan/.sphinx"
  430. */
  431. pwd = k_getpwnam(UserNameRequested);
  432. if (pwd == NULL) {
  433. return(AUTH_USER); /* not authenticated */
  434. }
  435. snprintf (acl_file, sizeof(acl_file),
  436. "%s/.sphinx", pwd->pw_dir);
  437. acl_file_buffer.value = acl_file;
  438. acl_file_buffer.length = strlen(acl_file);
  439. major_status = gss_display_name(&status,
  440. src_name,
  441. &fullname_buffer,
  442. &fullname_type);
  443. if (level < AUTH_USER)
  444. return(level);
  445. major_status = gss__check_acl(&status, &fullname_buffer,
  446. &acl_file_buffer);
  447. if (major_status == GSS_S_COMPLETE) {
  448. strlcpy(name, UserNameRequested, name_sz);
  449. return(AUTH_VALID);
  450. } else {
  451. return(AUTH_USER);
  452. }
  453. }
  454. #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
  455. #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
  456. void
  457. spx_printsub(unsigned char *data, size_t cnt,
  458. unsigned char *buf, size_t buflen)
  459. {
  460. size_t i;
  461. buf[buflen-1] = '\0'; /* make sure it's NULL terminated */
  462. buflen -= 1;
  463. switch(data[3]) {
  464. case SPX_REJECT: /* Rejected (reason might follow) */
  465. strlcpy((char *)buf, " REJECT ", buflen);
  466. goto common;
  467. case SPX_ACCEPT: /* Accepted (name might follow) */
  468. strlcpy((char *)buf, " ACCEPT ", buflen);
  469. common:
  470. BUMP(buf, buflen);
  471. if (cnt <= 4)
  472. break;
  473. ADDC(buf, buflen, '"');
  474. for (i = 4; i < cnt; i++)
  475. ADDC(buf, buflen, data[i]);
  476. ADDC(buf, buflen, '"');
  477. ADDC(buf, buflen, '\0');
  478. break;
  479. case SPX_AUTH: /* Authentication data follows */
  480. strlcpy((char *)buf, " AUTH", buflen);
  481. goto common2;
  482. default:
  483. snprintf(buf, buflen, " %d (unknown)", data[3]);
  484. common2:
  485. BUMP(buf, buflen);
  486. for (i = 4; i < cnt; i++) {
  487. snprintf(buf, buflen, " %d", data[i]);
  488. BUMP(buf, buflen);
  489. }
  490. break;
  491. }
  492. }
  493. #endif
  494. #ifdef notdef
  495. prkey(msg, key)
  496. char *msg;
  497. unsigned char *key;
  498. {
  499. int i;
  500. printf("%s:", msg);
  501. for (i = 0; i < 8; i++)
  502. printf(" %3d", key[i]);
  503. printf("\r\n");
  504. }
  505. #endif