home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckuath.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  409KB  |  13,363 lines

  1. char *ckathv = "Authentication, 9.0.235, 16 Mar 2010";
  2. /*
  3.   C K U A T H . C  --  Authentication for C-Kermit
  4.  
  5.   Copyright (C) 1999, 2010,
  6.     Trustees of Columbia University in the City of New York.
  7.     All rights reserved.  See the C-Kermit COPYING.TXT file or the
  8.     copyright text in the ckcmai.c module for disclaimer and permissions.
  9.  
  10.     Author:  Jeffrey E Altman (jaltman@secure-endpoints.com)
  11.                Secure Endpoints Inc., New York City
  12. */
  13. /*
  14.  * Additional copyrights included with affected code.
  15.  */
  16.  
  17. #ifdef HEIMDAL
  18. /*
  19.   Turned off User to User support
  20.   Turned off KDESTROY support
  21.   Turned off KLIST support
  22.   Turned off krb5_prompter() support
  23.   Turned off ticket validation
  24.   Turned off ticket renewal
  25.   Turned off alternative cache support in k5_get_ccache()
  26.  
  27.   Remaining link problems:
  28.  
  29.   ckuath.o: In function `ck_krb5_initTGT':
  30.   ckuath.o(.text+0x50c2): undefined reference to `krb5_string_to_deltat'
  31.   ckuath.o(.text+0x516d): undefined reference to `krb5_string_to_deltat'
  32.   ckuath.o(.text+0x51ef): undefined reference to `krb5_string_to_deltat'
  33. */
  34. #endif /* HEIMDAL */
  35.  
  36. /*
  37.  * Implements Kerberos 4/5, SRP, SSL, NTLM authentication and START_TLS
  38.  */
  39.  
  40. #include "ckcsym.h"
  41. #include "ckcdeb.h"
  42.  
  43. #ifdef CK_SECURITY
  44.  
  45. #define CKUATH_C
  46. #include "ckcker.h"
  47. #include "ckuusr.h"
  48. #include "ckucmd.h"                             /* For struct keytab */
  49. #include "ckcnet.h"
  50. #include "ckctel.h"
  51.  
  52. char szUserNameRequested[UIDBUFLEN+1];    /* for incoming connections */
  53. char szUserNameAuthenticated[UIDBUFLEN+1];/* for incoming connections */
  54. char szHostName[UIDBUFLEN+1];
  55. char szUserName[UIDBUFLEN+1];
  56. static char szIP[16];
  57. static int  validUser = AUTH_REJECT;    /* User starts out invalid */
  58. int authentication_version = AUTHTYPE_NULL;
  59. int accept_complete = 0;
  60.  
  61. #ifdef CK_AUTHENTICATION
  62. #ifdef CK_SSL
  63. #ifdef KRB5
  64. #define TLS_VERIFY
  65. #endif /* KRB5 */
  66. #endif /* CK_SSL */
  67.  
  68. #ifdef CK_DES
  69. #ifdef CK_SSL
  70. #ifndef LIBDES
  71. #define LIBDES
  72. #endif /* LIBDES */
  73. #endif /* CK_SSL */
  74. #endif /* CK_DES */
  75.  
  76. #ifdef CRYPT_DLL
  77. #ifndef LIBDES
  78. #define LIBDES
  79. #endif /* LIBDES */
  80. #ifdef OS2
  81. #ifdef NT
  82. #include <windows.h>
  83. #else /* NT */
  84. #define INCL_DOSMODULEMGR
  85. #include <os2.h>
  86. #endif /* NT */
  87. #endif /* OS2 */
  88. #endif /* CRYPT_DLL */
  89.  
  90. #ifdef NT
  91. #define KRB5_AUTOCONF__
  92. #define NTLM
  93. #endif /* NT */
  94.  
  95. #ifdef CK_KERBEROS
  96. #define KINIT
  97. #ifndef HEIMDAL
  98. #define KLIST
  99. #define KDESTROY
  100. #endif /* HEIMDAL */
  101. #define CHECKADDRS
  102. #else /* CK_KERBEROS */
  103. #ifdef KRB4
  104. #undef KRB4
  105. #endif /* KRB4 */
  106. #ifdef KRB5
  107. #undef KRB5
  108. #endif /* KRB5 */
  109. #ifdef KRB524
  110. #undef KRB524
  111. #endif /* KRB524 */
  112. #endif /* CK_KERBEROS */
  113.  
  114. #include <stdlib.h>
  115. #include <string.h>
  116. #include <stdio.h>
  117. #include <time.h>
  118. #include <fcntl.h>
  119. #include <errno.h>
  120. #ifndef malloc
  121. #ifndef VMS
  122. #ifndef FREEBSD4
  123. #ifndef OpenBSD
  124. #ifdef MACOSX
  125. #include <sys/malloc.h>
  126. #else /* MACOSX */
  127. #include <malloc.h>
  128. #endif /* MACOSX */
  129. #endif /* OpenBSD */
  130. #endif /* FREEBSD4 */
  131. #endif /* VMS */
  132. #endif /* malloc */
  133. #ifdef OS2
  134. #include <io.h>
  135. #endif /* OS2 */
  136.  
  137. #ifdef KRB5
  138. #ifdef HEIMDAL
  139. #ifdef printf
  140. #define saveprintf printf
  141. #undef printf
  142. #endif /* printf */
  143. #include "krb5.h"
  144.  
  145. #include "com_err.h"
  146.  
  147. #ifdef saveprintf
  148. #define printf saveprintf
  149. #endif /* saveprintf */
  150. #else /* HEIMDAL */
  151. #include "krb5.h"
  152. #include "profile.h"
  153. #include "com_err.h"
  154. #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
  155. #define KRB5_HAVE_GET_INIT_CREDS
  156. #else
  157. #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val))
  158. #endif
  159. #ifndef KRB5_HAVE_GET_INIT_CREDS
  160. #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data)
  161. #endif
  162. #endif /* HEIMDAL */
  163. #ifdef HAVE_PWD_H
  164. #include <pwd.h>
  165. #endif
  166. #endif /* KRB5 */
  167.  
  168. #ifdef KRB4
  169. #define  des_cblock Block
  170. #define  const_des_cblock const Block
  171. #define  des_key_schedule Schedule
  172. #ifdef KRB524
  173. #ifdef NT
  174. #define _WINDOWS
  175. #endif /* NT */
  176. #include "kerberosIV/krb.h"
  177. #ifndef OS2
  178. #ifdef KRB524_CONV
  179. #include "krb524.h"
  180. #endif /* KRB524_CONV */
  181. _PROTOTYP(const char * krb_get_err_text_entry, (int));
  182. #endif /* OS2 */
  183. #else /* KRB524 */
  184. #ifdef SOLARIS
  185. #ifndef sun
  186. /* for some reason the Makefile entries for the Solaris systems have -Usun */
  187. #define sun
  188. #endif /* sun */
  189. #endif /* SOLARIS */
  190. #include "krb.h"
  191. #define krb_get_err_text_entry krb_get_err_text
  192. #endif /* KRB524 */
  193. #else /* KRB4 */
  194. #ifdef CK_SSL
  195. #define  des_cblock Block
  196. #ifdef COMMENT
  197. #define  const_des_cblock const Block
  198. #endif /* COMMENT */
  199. #define  des_key_schedule Schedule
  200. #endif /* CK_SSL */
  201. #endif /* KRB4 */
  202.  
  203. #include "ckuath.h"
  204. #ifdef CK_KERBEROS
  205. #ifndef KRB5
  206. #define NOBLOCKDEF
  207. #else /* KRB5 */
  208. #ifdef KRB524
  209. #define NOBLOCKDEF
  210. #endif /* KRB524 */
  211. #endif /* KRB5 */
  212. #endif /* CK_KERBEROS */
  213. #include "ckuat2.h"
  214.  
  215. #ifdef CK_SSL
  216. #ifdef LIBDES
  217. #ifdef OPENSSL_097
  218. #ifdef CK_DES
  219. #define OPENSSL_ENABLE_OLD_DES_SUPPORT
  220. #include <openssl/des.h>
  221. #endif    /* CK_DES */
  222. #endif /* OPENSSL_097 */
  223. #ifndef HEADER_DES_H
  224. #define HEADER_DES_H
  225. #endif /* HEADER_DES_H */
  226. #endif /* LIBDES */
  227. #include "ck_ssl.h"
  228. extern int ssl_finished_messages;
  229. #endif /* SSL */
  230.  
  231. #define PWD_SZ 128
  232.  
  233. #ifndef LIBDES
  234. #ifdef UNIX
  235. #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
  236. #endif /* UNIX */
  237. #else /* LIBDES */
  238. #define des_fixup_key_parity des_set_odd_parity
  239. #endif /* LIBDES */
  240.  
  241. #ifdef OS2
  242. #ifdef CK_ENCRYPTION
  243. #define MAP_DES
  244. #endif /* CK_ENCRYPTION */
  245. #ifdef KRB4
  246. #define MAP_KRB4
  247. #endif /* KRB4 */
  248. #ifdef SRPDLL
  249. #define MAP_SRP
  250. #endif /* SRPDLL */
  251. #ifdef KRB5
  252. #define MAP_KRB5
  253. #endif /* KRB5 */
  254. #ifdef CRYPT_DLL
  255. #define MAP_CRYPT
  256. #endif /* CRYPT_DLL */
  257. #define MAP_NTLM
  258. #include "ckoath.h"
  259. #include "ckosyn.h"
  260. #endif /* OS2 */
  261.  
  262. /*
  263.  * Globals
  264.  */
  265. int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
  266. int auth_how=0;
  267. int auth_crypt=0;
  268. int auth_fwd=0;
  269.  
  270. /* These are state completion variables */
  271. static int mutual_complete = 0;
  272.  
  273. #ifdef KRB4
  274. #ifdef OS2
  275. static LEASH_CREDENTIALS cred;
  276. #else /* OS2 */
  277. static CREDENTIALS cred;
  278. #endif /* OS2 */
  279. static KTEXT_ST k4_auth;
  280. static char     k4_name[ANAME_SZ];
  281. static AUTH_DAT k4_adat  = { 0 };
  282. static MSG_DAT  k4_msg_data;
  283. #ifdef CK_ENCRYPTION
  284. static Block    k4_session_key     = { 0 };
  285. static Schedule k4_sched;
  286. static Block    k4_challenge       = { 0 };
  287. #ifdef MIT_CURRENT
  288. static krb5_keyblock k4_krbkey;
  289. #endif /* MIT_CURRENT */
  290. #endif /* ENCRYPTION */
  291. #define KRB4_SERVICE_NAME    "rcmd"
  292.  
  293. _PROTOTYP(static int k4_auth_send,(VOID));
  294. _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
  295. _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
  296. #endif /* KRB4 */
  297.  
  298. #ifdef KRB5
  299. static krb5_data          k5_auth;
  300. static krb5_auth_context  auth_context;
  301. static krb5_keyblock     *k5_session_key = NULL;
  302. static krb5_ticket       *k5_ticket = NULL;
  303. #ifndef KRB5_SERVICE_NAME
  304. #define KRB5_SERVICE_NAME    "host"
  305. #ifdef MACOSX
  306. #define MIT_CURRENT 1
  307. #define decode_krb5_ticket  krb5_decode_ticket
  308. #define krb5_read_message   ck_krb5_read_message
  309. #define krb5_write_message  ck_krb5_write_message
  310. #endif /* MACOSX */
  311. #endif
  312.  
  313. _PROTOTYP(static int k5_auth_send,(int,int,int));
  314. _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
  315. _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
  316. _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
  317. #ifdef TLS_VERIFY
  318. static int krb5_tls_verified = 0;
  319. #endif /* TLS_VERIFY */
  320. #endif /* KRB5 */
  321.  
  322. #ifdef GSSAPI_KRB5
  323. #include <gssapi/gssapi.h>
  324. #include <gssapi/gssapi_generic.h>
  325. #include <gssapi/gssapi_krb5.h>
  326.  
  327. static gss_ctx_id_t gcontext;
  328. #define GSS_BUFSIZ 4096
  329. static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr;
  330. static char gss_stbuf[GSS_BUFSIZ];
  331. static gss_name_t gss_target_name;
  332. static struct gss_channel_bindings_struct gss_chan;
  333.  
  334. _PROTOTYP(static int gssk5_auth_send,(int,int,int));
  335. _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int));
  336. _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int));
  337. _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int));
  338. #endif /* GSSAPI_KRB5 */
  339.  
  340. #ifdef CK_SRP
  341. #ifdef PRE_SRP_1_7_3
  342. _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
  343. _PROTOTYP(static int srp_is,(int, unsigned char *, int));
  344. #else /* PRE_SRP_1_7_3 */
  345. _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int));
  346. _PROTOTYP(static int new_srp_is,(int, unsigned char *, int));
  347. #endif /* PRE_SRP_1_7_3 */
  348. #endif /* SRP */
  349.  
  350. #ifdef CK_ENCRYPTION
  351. int encrypt_flag = 1;
  352. #endif
  353. #ifdef FORWARD
  354. int forward_flag = 0;              /* forward tickets? */
  355. int forwardable_flag = 1;          /* get forwardable tickets to forward? */
  356. int forwarded_tickets = 0;         /* were tickets forwarded? */
  357. #endif
  358.  
  359. static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  360.                                         AUTHTYPE_KERBEROS_V5, };
  361. #define AUTHTMPBL 2048
  362. static char strTmp[AUTHTMPBL+1];
  363. static char szLocalHostName[UIDBUFLEN+1];
  364. static kstream g_kstream=NULL;
  365.  
  366. #ifdef KRB5
  367. krb5_context k5_context=NULL;
  368. static krb5_creds * ret_cred=NULL;
  369. static krb5_context telnet_context=NULL;
  370. static char * telnet_krb5_realm = NULL;
  371. static krb5_principal fwd_server = NULL;
  372. #endif /* KRB5 */
  373.  
  374. #ifdef CK_SRP
  375. #ifdef PRE_SRP_1_4_4
  376. #ifndef PRE_SRP_1_4_5
  377. #define PRE_SRP_1_4_5
  378. #endif /* PRE_SRP_1_4_5 */
  379. #endif /* PRE_SRP_1_4_5 */
  380. #ifdef PRE_SRP_1_4_5
  381. #ifndef PRE_SRP_1_7_3
  382. #define PRE_SRP_1_7_3
  383. #endif /* PRE_SRP_1_7_3 */
  384. #endif /* PRE_SRP_1_4_5 */
  385. #include <t_pwd.h>
  386. #include <t_client.h>
  387. #include <t_server.h>
  388. static struct t_server * ts = NULL;
  389. static struct t_client * tc = NULL;
  390. #ifdef PRE_SRP_1_4_4
  391. static struct t_pw * tpw = NULL;
  392. static struct t_conf * tconf = NULL;
  393. #endif /* PRE_SRP_1_4_4 */
  394. #ifndef PRE_SRP_1_7_3
  395. #ifndef STDC_HEADERS
  396. #define STDC_HEADERS 1
  397. #endif /* STDC_HEADERS */
  398. #include <srp.h>
  399. static SRP * s_srp = NULL;
  400. static cstr * s_key = NULL;
  401. static SRP * c_srp = NULL;
  402. static cstr * c_key = NULL;
  403. #endif /* PRE_SRP_1_7_3 */
  404. static int srp_waitresp = 0;    /* Flag to indicate readiness for response */
  405. static char srp_passwd[PWD_SZ];
  406. #endif /* CK_SRP */
  407.  
  408. #ifdef CK_KERBEROS
  409. #ifdef RLOGCODE
  410. #define OPTS_FORWARD_CREDS           0x00000020
  411. #define OPTS_FORWARDABLE_CREDS       0x00000010
  412. #define KCMD_KEYUSAGE                1026
  413.  
  414. #define RLOG_BUFSIZ 5120
  415. static int rlog_encrypt = 0;
  416. char des_inbuf[2*RLOG_BUFSIZ];       /* needs to be > largest read size */
  417. char des_outpkt[2*RLOG_BUFSIZ+4];    /* needs to be > largest write size */
  418. #ifdef KRB5
  419. krb5_data desinbuf,desoutbuf;
  420. krb5_encrypt_block eblock;             /* eblock for encrypt/decrypt */
  421. static krb5_data encivec_i[2], encivec_o[2];
  422.  
  423. enum krb5_kcmd_proto {
  424.   /* Old protocol: DES encryption only.  No subkeys.  No protection
  425.      for cleartext length.  No ivec supplied.  OOB hacks used for
  426.      rlogin.  Checksum may be omitted at connection startup.  */
  427.   KCMD_OLD_PROTOCOL = 1,
  428.   /* New protocol: Any encryption scheme.  Client-generated subkey
  429.      required.  Prepend cleartext-length to cleartext data (but don't
  430.      include it in count).  Starting ivec defined, chained.  In-band
  431.      signalling.  Checksum required.  */
  432.   KCMD_NEW_PROTOCOL,
  433.   /* Hack: Get credentials, and use the old protocol iff the session
  434.      key type is single-DES.  */
  435.   KCMD_PROTOCOL_COMPAT_HACK,
  436.   KCMD_UNKNOWN_PROTOCOL
  437. };
  438. enum krb5_kcmd_proto krb5_rlog_ver = KCMD_PROTOCOL_COMPAT_HACK;
  439. #endif /* KRB5 */
  440. #endif /* RLOGCODE */
  441. static char storage[65536];            /* storage for the decryption */
  442. static int nstored = 0;
  443. static char *store_ptr = storage;
  444.  
  445. extern char * krb5_d_principal;         /* Default principal */
  446. extern char * krb5_d_instance;          /* Default instance */
  447. extern char * krb5_d_realm;             /* Default realm */
  448. extern char * krb5_d_cc;                /* Default credentials cache */
  449. extern char * krb5_d_srv;               /* Default service name */
  450. extern int    krb5_d_lifetime;          /* Default lifetime */
  451. extern int    krb5_d_forwardable;
  452. extern int    krb5_d_proxiable;
  453. extern int    krb5_d_renewable;
  454. extern int    krb5_autoget;
  455. extern int    krb5_checkaddrs;
  456. extern int    krb5_d_getk4;
  457. extern int    krb5_d_no_addresses;
  458. extern char * k5_keytab;
  459.  
  460. extern int    krb5_errno;
  461. extern char * krb5_errmsg;
  462.  
  463. extern char * krb4_d_principal;         /* Default principal */
  464. extern char * krb4_d_realm;             /* Default realm */
  465. extern char * krb4_d_srv;               /* Default service name */
  466. extern int    krb4_d_lifetime;          /* Default lifetime */
  467. extern int    krb4_d_preauth;
  468. extern char * krb4_d_instance;
  469. extern int    krb4_autoget;
  470. extern int    krb4_checkaddrs;
  471. extern char * k4_keytab;
  472.  
  473. extern int    krb4_errno;
  474. extern char * krb4_errmsg;
  475. #endif /* CK_KERBEROS */
  476.  
  477. extern char tn_msg[], hexbuf[];         /* from ckcnet.c */
  478. extern CHAR pwbuf[];
  479. extern int  pwflg, pwcrypt;
  480. extern int deblog, debses, tn_deb;
  481. extern int sstelnet, inserver;
  482. #ifdef CK_LOGIN
  483. extern int ckxanon;
  484. #endif /* CK_LOGIN */
  485. extern int tn_auth_how;
  486. extern int tn_auth_enc;
  487. #ifdef CK_ENCRYPTION
  488. extern int cx_type;
  489. #endif /* CK_ENCRYPTION */
  490. extern int quiet, ttyfd, ttnproto;
  491.  
  492. int
  493. ck_gssapi_is_installed()
  494. {
  495. #ifdef KRB5
  496. #ifdef OS2
  497.     return(hGSSAPI != NULL);
  498. #else /* OS2 */
  499.     return(1);
  500. #endif /* OS2 */
  501. #else /* KRB5 */
  502.     return(0);
  503. #endif /* KRB5 */
  504. }
  505.  
  506. int
  507. ck_krb5_is_installed()
  508. {
  509. #ifdef KRB5
  510. #ifdef OS2
  511.     return(hKRB5_32 != NULL);
  512. #else /* OS2 */
  513.     return(1);
  514. #endif /* OS2 */
  515. #else /* KRB5 */
  516.     return(0);
  517. #endif /* KRB5 */
  518. }
  519.  
  520.  
  521. int
  522. ck_krb5_is_installed_as_server()
  523. {
  524. #ifdef KRB5
  525. #ifdef HEIMDAL
  526.     krb5_error_code ret;
  527.     krb5_keytab kt;
  528.     krb5_kt_cursor cursor;
  529.  
  530.     ret = krb5_kt_default(k5_context, &kt);
  531.     if ( ret ) {
  532.         krb5_kt_close(k5_context, kt);
  533.         return(0);
  534.     } else {
  535.         krb5_kt_end_seq_get(k5_context, kt, &cursor);
  536.         krb5_kt_close(k5_context, kt);
  537.         return(1);
  538.     }
  539. #else /* HEIMDAL */
  540. #ifndef COMMENT
  541.     char ktname[CKMAXPATH]="";
  542.  
  543.     if ( k5_keytab ) {
  544.         ckstrncpy(ktname,k5_keytab,CKMAXPATH);
  545.     } else {
  546.         krb5_error_code code;
  547.  
  548.         if ( k5_context == NULL)
  549.             if (krb5_init_context(&k5_context))
  550.                 return(0);
  551.  
  552.         code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH);
  553.         debug(F101,"krb5_kt_default_name","",code);
  554.         if ( code ) {
  555.             /* We can't check the existence of the file since we can't   */
  556.             /* determine the file name.  So we return TRUE and let       */
  557.             /* Krb5 be offered to the user even though it may fail later */
  558.             return(1);
  559.         }
  560.     }
  561.  
  562.     if ( !strncmp("FILE:",ktname,5) ) {
  563.         if ( zchki(&ktname[5]) > 0 )
  564.             return(1);
  565.         else
  566.             return(0);
  567.     } else {
  568.         if (ktname[0])
  569.             return(1);
  570.         else
  571.             return(0);
  572.     }
  573. #else /* COMMENT */
  574.     krb5_error_code             krb5rc = KRB5KRB_ERR_GENERIC;
  575.     krb5_context                krb5context = NULL;
  576.     krb5_ccache                 krb5ccdef = NULL;
  577.     krb5_creds                  krb5creds, *krb5credsp = NULL;
  578.     int                         rc = 0;
  579.  
  580.     if ( !ck_krb5_is_installed() )
  581.         return(0);
  582.  
  583.     memset((char *)&krb5creds, 0, sizeof(krb5creds));
  584.  
  585.     if ((krb5rc = krb5_init_context(&krb5context)) != 0)
  586.         goto err;
  587.  
  588.     if ((krb5rc = krb5_sname_to_principal(krb5context,
  589.                                           szHostName,
  590.                                           krb5_d_srv ?
  591.                                           krb5_d_srv :
  592.                                           KRB5_SERVICE_NAME,
  593.                                           KRB5_NT_SRV_HST,
  594.                                           &krb5creds.server)) != 0)
  595.       goto err;
  596.  
  597.     if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
  598.         goto err;
  599.  
  600.     if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
  601.                                          &krb5creds.client)) != 0)
  602.         goto err;
  603.  
  604.     if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
  605.                                         &krb5creds, &krb5credsp)) != 0)
  606.         goto err;
  607.     rc = 1;
  608.  
  609.   err:
  610.  
  611.     if (krb5creds.client)
  612.       krb5_free_principal(krb5context, krb5creds.client);
  613.     if (krb5creds.server)
  614.       krb5_free_principal(krb5context, krb5creds.server);
  615.     if (krb5context)
  616.       krb5_free_context(krb5context);
  617.     return(rc);
  618.  
  619. #endif /* COMMENT */
  620. #endif /* HEIMDAL */
  621. #else /* KRB5 */
  622.     return(0);
  623. #endif /* KRB5 */
  624. }
  625.  
  626. int
  627. ck_krb4_is_installed()
  628. {
  629. #ifdef KRB4
  630. #ifdef OS2
  631.     return(hKRB4_32 != NULL);
  632. #else /* OS2 */
  633.     return(1);
  634. #endif /* OS2 */
  635. #else /* KRB4 */
  636.     return(0);
  637. #endif /* KRB4 */
  638. }
  639.  
  640. int
  641. ck_krb4_is_installed_as_server()
  642. {
  643.     if ( !ck_krb4_is_installed() )
  644.         return(0);
  645.  
  646. #ifdef KRB4
  647.     if ( !k4_keytab ) {
  648. #ifdef NT
  649.         char name[CKMAXPATH]="";
  650.         DWORD len = CKMAXPATH;
  651.  
  652.         len = GetWindowsDirectory(name,len);
  653.         if ( len > 0 )
  654.             ckstrncat(name,"/srvtab",CKMAXPATH);
  655.         if ( name[0] )
  656.             makestr(&k4_keytab,name);
  657. #else /* NT */
  658.         makestr(&k4_keytab,"/etc/srvtab");
  659. #endif /* NT */
  660.     }
  661.  
  662.     if ( !k4_keytab )
  663.         return(0);
  664.  
  665.     if ( zchki(k4_keytab) > 0 )
  666.         return(1);
  667. #ifdef KRB524
  668.     else if (ck_krb5_is_installed_as_server())
  669.         return(1);
  670. #endif /* KRB524 */
  671.     else
  672.         return(0);
  673. #endif /* KRB4 */
  674. }
  675.  
  676. int
  677. ck_srp_is_installed_as_server()
  678. {
  679. #ifdef CK_SRP
  680. #ifdef SRPDLL
  681.     if ( hSRP == NULL )
  682.         return(0);
  683. #endif /* SRPDLL */
  684. #ifdef COMMENT
  685.     /* This is the new API as of 1.7.4.  However, all it does
  686.        is allocate a data structure.  It can never fail.
  687.      */
  688.     {
  689.         SRP * s_srp = SRP_new(SRP_RFC2945_server_method());
  690.         if ( s_srp ) {
  691.             SRP_free(s_srp);
  692.             s_srp = NULL;
  693.             return(1);
  694.         }
  695.         return(0);
  696.     }
  697. #else /* COMMENT */
  698.     {
  699.         struct t_pw * tpw = NULL;
  700.         struct t_conf * tconf = NULL;
  701.         if((tconf = t_openconf(NULL)) == NULL)
  702.             return(0);
  703.         if((tpw = t_openpw(NULL)) == NULL) {
  704.             t_closeconf(tconf);
  705.             return(0);
  706.         }
  707.         t_closeconf(tconf);
  708.         t_closepw(tpw);
  709.         return(1);
  710.     }
  711. #endif /* COMMENT */
  712. #else /* SRP */
  713.     return(0);
  714. #endif /* SRP */
  715. }
  716.  
  717. int
  718. ck_srp_is_installed()
  719. {
  720. #ifdef CK_SRP
  721. #ifdef SRPDLL
  722.     if ( hSRP == NULL )
  723.         return(0);
  724. #endif /* SRPDLL */
  725.     return(1);
  726. #else /* CK_SRP */
  727.     return(0);
  728. #endif /* CK_SRP */
  729. }
  730.  
  731. int
  732. ck_krypto_is_installed()
  733. {
  734. #ifdef CK_SRP
  735. #ifdef OS2
  736.     if ( hLIBKRYPTO == NULL )
  737.         return(0);
  738. #endif /* OS2 */
  739.     return(1);
  740. #else /* CK_SRP */
  741.     return(0);
  742. #endif /* CK_SRP */
  743. }
  744.  
  745. int
  746. ck_crypt_is_installed()
  747. {
  748. #ifdef CK_ENCRYPTION
  749. #ifdef CRYPT_DLL
  750.     return(hCRYPT != NULL);
  751. #else /* CRYPT_DLL */
  752.     return(1);
  753. #endif /* CRYPT_DLL */
  754. #else /* ENCRYPTION */
  755.     return(0);
  756. #endif /* ENCRYPTION */
  757. }
  758.  
  759. int
  760. ck_ntlm_is_installed()
  761. {
  762. #ifdef NT
  763.     return(hSSPI != NULL);
  764. #else /* NT */
  765.     return(0);
  766. #endif /* NT */
  767. }
  768.  
  769. int
  770. ck_tn_auth_valid()
  771. {
  772.     return(validUser);
  773. }
  774.  
  775. /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
  776.  *
  777.  * Is an authentication negotiation still in progress?
  778.  *
  779.  */
  780.  
  781. int
  782. #ifdef CK_ANSIC
  783. ck_tn_auth_in_progress(void)
  784. #else
  785. ck_tn_auth_in_progress()
  786. #endif
  787. {
  788.     switch (authentication_version) {
  789.     case AUTHTYPE_AUTO:
  790.         return(1);
  791.     case AUTHTYPE_NULL:
  792.         return(0);
  793. #ifdef KRB4
  794.     case AUTHTYPE_KERBEROS_V4:
  795.         if (!accept_complete) {
  796.             debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
  797.                    "",0);
  798.             return(1);
  799.         }
  800.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  801.             debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
  802.                    "",0);
  803.             return(1);
  804.         }
  805.         else
  806.             return(0);
  807. #endif /* KRB4 */
  808. #ifdef KRB5
  809.     case AUTHTYPE_KERBEROS_V5:
  810.         if (!accept_complete) {
  811.             debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
  812.                    "",0);
  813.             return(1);
  814.         }
  815.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  816.             debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
  817.                    "",0);
  818.             return(1);
  819.         }
  820.         else
  821.             return(0);
  822. #ifdef GSSAPI_K5
  823.     case AUTHTYPE_GSSAPI_KRB5:
  824.         if (!accept_complete) {
  825.             debug(F100,
  826.           "ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete",
  827.           "",
  828.           0
  829.           );
  830.             return(1);
  831.         }
  832.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  833.             debug(F100,
  834.           "ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete",
  835.           "",
  836.           0
  837.           );
  838.             return(1);
  839.         } else
  840.       return(0);
  841.         break;
  842. #endif /* GSSAPI_K5 */
  843. #endif /* KRB5 */
  844. #ifdef CK_SRP
  845.     case AUTHTYPE_SRP:
  846.         if (!accept_complete || srp_waitresp)
  847.             return(1);
  848.         else
  849.             return(0);
  850. #endif /* CK_SRP */
  851. #ifdef NTLM
  852.     case AUTHTYPE_NTLM:
  853.         if (!accept_complete) {
  854.             debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
  855.                    "",0);
  856.             return(1);
  857.         }
  858.         else
  859.             return(0);
  860. #endif /* NTLM */
  861.     case AUTHTYPE_SSL:
  862.         if (!accept_complete) {
  863.             debug(F100,"ck_auth_in_progress() SSL !accept_complete",
  864.                    "",0);
  865.             return(1);
  866.         }
  867.         else
  868.             return(0);
  869.     default:
  870.         return(0);
  871.     }
  872.     return(0);
  873. }
  874.  
  875.  
  876. /*  C K _ K R B _ T N _ A U T H _ R E Q U E S T
  877.  *
  878.  *  Builds a Telnet Authentication Send Negotiation providing the
  879.  *  list of supported authentication methods.  To be used only
  880.  *  when accepting incoming connections as only the server (DO) side of the
  881.  *  Telnet negotiation is allowed to send an AUTH SEND.
  882.  *
  883.  *  Returns: 0 on success and -1 on failure
  884.  */
  885.  
  886. static unsigned char str_request[64] = { IAC, SB,
  887.                                              TELOPT_AUTHENTICATION,
  888.                                              TELQUAL_SEND };
  889. #ifdef GSSAPI_K5
  890. static int
  891. ck_tn_auth_request_gsskrb5(int i)
  892. {
  893.     if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) {
  894.         if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
  895.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  896.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  897.                tn_auth_enc == TN_AUTH_ENC_EXCH) ) {
  898.             str_request[i++] = AUTHTYPE_KERBEROS_V5;
  899.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  900.             str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE;
  901.  
  902.             if ( deblog || tn_deb || debses )
  903.                 ckstrncat(tn_msg,
  904.                 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ",
  905.                           TN_MSG_LEN);
  906.             i++;
  907.         }
  908.     }
  909. }
  910. #endif /* GSSAPI_K5 */
  911.  
  912. #ifdef KRB5
  913. static int
  914. ck_tn_auth_request_krb5(int i)
  915. {
  916.     if (ck_krb5_is_installed_as_server()) {
  917. #ifdef CK_SSL
  918.         if ( ck_ssleay_is_installed() &&
  919.              (tls_active_flag || ssl_active_flag) &&
  920.              ssl_finished_messages )
  921.         {
  922. #ifdef USE_INI_CRED_FWD
  923.             if ( forward_flag &&
  924.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  925.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  926.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  927.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  928.                  )
  929.             {
  930.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  931.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  932.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  933.                 str_request[i] |= INI_CRED_FWD_ON;
  934.  
  935.                 if ( deblog || tn_deb || debses )
  936.                     ckstrncat(tn_msg,
  937.  "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ",
  938.                                TN_MSG_LEN);
  939.                 i++;
  940.             }
  941. #endif /* USE_INI_CRED_FWD */
  942.             if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
  943.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  944.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  945.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  946.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  947.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  948.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  949.  
  950.                 if ( deblog || tn_deb || debses )
  951.                     ckstrncat(tn_msg,
  952.                       "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ",
  953.                               TN_MSG_LEN);
  954.                 i++;
  955.             }
  956.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  957.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  958.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  959.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  960.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  961.  
  962.                 if ( deblog || tn_deb || debses )
  963.                     ckstrncat(tn_msg,
  964.                     "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
  965.                                TN_MSG_LEN);
  966.                 i++;
  967.             }
  968.         }
  969. #ifdef CK_ENCRYPTION
  970.         else
  971.         {
  972. #endif /* CK_ENCRYPTION */
  973. #endif /* CK_SSL */
  974. #ifdef CK_ENCRYPTION
  975. #ifdef USE_INI_CRED_FWD
  976.             if ( forward_flag &&
  977.                  TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  978.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  979.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  980.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  981.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  982.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  983.                  )
  984.             {
  985.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  986.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  987.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  988.                 str_request[i] |= INI_CRED_FWD_ON;
  989.  
  990.                 if ( deblog || tn_deb || debses )
  991.                     ckstrncat(tn_msg,
  992.   "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ",
  993.                                TN_MSG_LEN);
  994.                 i++;
  995.             }
  996. #endif /* USE_INI_CRED_FWD */
  997.  
  998.             if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  999.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1000.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1001.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1002.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1003.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  1004.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1005.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1006.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1007.  
  1008.                 if ( deblog || tn_deb || debses )
  1009.                     ckstrncat(tn_msg,
  1010.               "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ",
  1011.                                TN_MSG_LEN);
  1012.                 i++;
  1013.             }
  1014. #ifdef CK_SSL
  1015.         }
  1016. #endif /* CK_SSL */
  1017. #endif /* CK_ENCRYPTION */
  1018.  
  1019.         if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1020.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1021.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1022.                tn_auth_enc == TN_AUTH_ENC_NONE)
  1023. #ifdef CK_SSL
  1024.              && !(ck_ssleay_is_installed() &&
  1025.                    (tls_active_flag || ssl_active_flag) &&
  1026.                    tls_is_anon(0))
  1027. #endif /* CK_SSL */
  1028.              )
  1029.         {
  1030. #ifdef CK_ENCRYPTION
  1031.             /* Can't perform mutual authentication without encryption */
  1032.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1033.                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1034.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1035.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1036.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1037.  
  1038.                 if ( deblog || tn_deb || debses )
  1039.                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ",
  1040.                                TN_MSG_LEN);
  1041.                 i++;
  1042.             }
  1043. #endif /* CK_ENCRYPTION */
  1044.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1045.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1046.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1047.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1048.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1049.  
  1050.                 if ( deblog || tn_deb || debses )
  1051.                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ",
  1052.                                TN_MSG_LEN);
  1053.                 i++;
  1054.             }
  1055.         }
  1056.     }
  1057.     return(i);
  1058. }
  1059. #endif /* KRB5 */
  1060. #ifdef KRB4
  1061. static int
  1062. ck_tn_auth_request_krb4(int i)
  1063. {
  1064.     if (ck_krb4_is_installed_as_server()) {
  1065. #ifdef CK_ENCRYPTION
  1066.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1067.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1068.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1069.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1070.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1071.                tn_auth_enc == TN_AUTH_ENC_TELOPT) )
  1072.         {
  1073.             str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1074.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1075.             str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1076.  
  1077.             if ( deblog || tn_deb || debses )
  1078.               ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ",
  1079.                         TN_MSG_LEN);
  1080.             i++;
  1081.         }
  1082. #endif /* CK_ENCRYPTION */
  1083.  
  1084.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1085.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1086.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1087.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1088.         {
  1089. #ifdef CK_ENCRYPTION
  1090.             /* Can't perform mutual authentication without encryption */
  1091.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1092.                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1093.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1094.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1095.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1096.  
  1097.                 if ( deblog || tn_deb || debses )
  1098.                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ",
  1099.                                TN_MSG_LEN);
  1100.                 i++;
  1101.             }
  1102. #endif /* CK_ENCRYPTION */
  1103.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1104.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1105.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1106.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1107.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1108.  
  1109.                 if ( deblog || tn_deb || debses )
  1110.                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ",
  1111.                                TN_MSG_LEN);
  1112.                 i++;
  1113.             }
  1114.         }
  1115.     }
  1116.  
  1117.     return(i);
  1118. }
  1119. #endif /* KRB4 */
  1120.  
  1121. #ifdef CK_SRP
  1122. static int
  1123. ck_tn_auth_request_srp(int i)
  1124. {
  1125.     if (ck_srp_is_installed_as_server()) {
  1126. #ifndef PRE_SRP_1_4_5
  1127.         /* Dont' do this yet.  SRP when it uses the ENCRYPT_USING_TELOPT   */
  1128.         /* flag it must perform a checksum of the auth-type-pair but there */
  1129.         /* is no mechansim to do that yet.                                 */
  1130. #ifdef CK_SSL
  1131.         if ( ck_ssleay_is_installed() &&
  1132.              (tls_active_flag || ssl_active_flag) &&
  1133.              ssl_finished_messages &&
  1134.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1135.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1136.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1137.                    tn_auth_enc == TN_AUTH_ENC_TELOPT))
  1138.         {
  1139.             str_request[i++] = AUTHTYPE_SRP;
  1140.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1141.             str_request[i] |= AUTH_ENCRYPT_START_TLS;
  1142.  
  1143.             if ( deblog || tn_deb || debses )
  1144.                 ckstrncat(tn_msg,
  1145.                            "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
  1146.                            TN_MSG_LEN);
  1147.             i++;
  1148.         }
  1149. #ifdef CK_ENCRYPTION
  1150.         else {
  1151. #endif /* CK_ENCRYPTION */
  1152. #endif /* CK_SSL */
  1153. #ifdef CK_ENCRYPTION
  1154.             if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1155.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1156.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1157.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1158.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1159.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  1160.                  ) {
  1161.                 str_request[i++] = AUTHTYPE_SRP;
  1162.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1163.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1164.  
  1165.                 if ( deblog || tn_deb || debses )
  1166.                     ckstrncat(tn_msg,
  1167.                     "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ",
  1168.                                TN_MSG_LEN);
  1169.                 i++;
  1170.             }
  1171. #ifdef CK_SSL
  1172.         }
  1173. #endif /* CK_SSL */
  1174. #endif /* CK_ENCRYPTION */
  1175. #endif /* PRE_SRP_1_4_5 */
  1176.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1177.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1178.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1179.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1180.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1181.                tn_auth_enc == TN_AUTH_ENC_NONE)
  1182. #ifdef CK_SSL
  1183.              && !(ck_ssleay_is_installed() &&
  1184.                    (tls_active_flag || ssl_active_flag) &&
  1185.                    tls_is_anon(0))
  1186. #endif /* CK_SSL */
  1187.              )
  1188.         {
  1189.             str_request[i++] = AUTHTYPE_SRP;
  1190.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1191.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1192.  
  1193.             if ( deblog || tn_deb || debses )
  1194.                 ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ",
  1195.                            TN_MSG_LEN);
  1196.             i++;
  1197.         }
  1198.     }
  1199.  
  1200.     return(i);
  1201. }
  1202. #endif /* CK_SRP */
  1203.  
  1204. #ifdef CK_SSL
  1205. static int
  1206. ck_tn_auth_request_ssl(int i)
  1207. {
  1208.     if (ck_ssleay_is_installed()
  1209.          && !tls_active_flag && !ssl_active_flag && ssl_initialized
  1210.          ) {
  1211.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1212.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1213.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1214.                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1215.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1216.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1217.         {
  1218.             str_request[i++] = AUTHTYPE_SSL;
  1219.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1220.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1221.             if ( deblog || tn_deb || debses )
  1222.                 ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ",
  1223.                            TN_MSG_LEN);
  1224.             i++;
  1225.         }
  1226.     }
  1227.  
  1228.     return(i);
  1229. }
  1230. #endif /* CK_SSL */
  1231. #ifdef NTLM
  1232. static int
  1233. ck_tn_auth_request_ntlm(int i)
  1234. {
  1235.     /* Microsoft's Telnet client won't perform authentication if */
  1236.     /* NTLM is not first.                                        */
  1237.     if ( ck_ntlm_is_valid(1) ) {
  1238.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1239.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1240.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1241.                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1242.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1243.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1244.         {
  1245.             str_request[i++] = AUTHTYPE_NTLM;
  1246.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1247.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1248.             if ( deblog || tn_deb || debses )
  1249.                 ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ",
  1250.                            TN_MSG_LEN);
  1251.             i++;
  1252.         }
  1253.     }
  1254.  
  1255.     return(i);
  1256. }
  1257. #endif /* NTLM */
  1258. int
  1259. #ifdef CK_ANSIC
  1260. ck_tn_auth_request(void)
  1261. #else
  1262. ck_tn_auth_request()
  1263. #endif
  1264. {
  1265.     int i = 4, rc = -1;
  1266.  
  1267. #ifdef CK_SSL
  1268.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1269.         return(0);
  1270.     }
  1271. #endif /* CK_SSL */
  1272.  
  1273.     if ( deblog || tn_deb || debses )
  1274.         strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
  1275.  
  1276.     /* Create a list of acceptable Authentication types to send to */
  1277.     /* the client and let it choose find one that we support       */
  1278.  
  1279.     /* For those authentication methods that support Encryption or */
  1280.     /* Credentials Forwarding we must send all of the appropriate  */
  1281.     /* combinations based upon the state of                        */
  1282.     /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag.          */
  1283.  
  1284.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  1285. #ifdef GSSAPI_K5
  1286.         i = ck_tn_auth_request_gsskrb5(i);
  1287. #endif /* GSSAPI_K5 */
  1288. #ifdef KRB5
  1289.         i = ck_tn_auth_request_krb5(i);
  1290. #endif /* KRB5 */
  1291. #ifdef KRB4
  1292.         i = ck_tn_auth_request_krb4(i);
  1293. #endif /* KRB4 */
  1294. #ifdef CK_SRP
  1295.         i = ck_tn_auth_request_srp(i);
  1296. #endif /* SRP */
  1297. #ifdef CK_SSL
  1298.         i = ck_tn_auth_request_ssl(i);
  1299. #endif /* CK_SSL */
  1300. #ifdef NTLM
  1301.         i = ck_tn_auth_request_ntlm(i);
  1302. #endif /* NTLM */
  1303.     } else {
  1304.         int j;
  1305.         for ( j=0;
  1306.               j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
  1307.               j++) {
  1308. #ifdef NTLM
  1309.             if (auth_type_user[j] == AUTHTYPE_NTLM)
  1310.                 i = ck_tn_auth_request_ntlm(i);
  1311. #endif /* NTLM */
  1312. #ifdef CK_SSL
  1313.             if ( auth_type_user[j] == AUTHTYPE_SSL )
  1314.                 i = ck_tn_auth_request_ssl(i);
  1315. #endif /* CK_SSL */
  1316. #ifdef CK_SRP
  1317.             if ( auth_type_user[j] == AUTHTYPE_SRP )
  1318.                 i = ck_tn_auth_request_srp(i);
  1319. #endif /* SRP */
  1320. #ifdef GSSAPI_K5
  1321.             if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 )
  1322.                 i = ck_tn_auth_request_gsskrb5(i);
  1323. #endif /* GSSAPI_K5 */
  1324. #ifdef KRB5
  1325.             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 )
  1326.                 i = ck_tn_auth_request_krb5(i);
  1327. #endif /* KRB5 */
  1328. #ifdef KRB4
  1329.             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 )
  1330.                 i = ck_tn_auth_request_krb4(i);
  1331. #endif /* KRB4 */
  1332.         }
  1333.     }
  1334.  
  1335.     str_request[i++] = IAC;
  1336.     str_request[i++] = SE;
  1337.     if ( deblog || tn_deb || debses ) {
  1338.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1339.         debug(F100,tn_msg,"",0);
  1340.         if (tn_deb || debses) tn_debug(tn_msg);
  1341.     }
  1342.  
  1343.     /* Send data */
  1344. #ifdef OS2
  1345.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1346. #endif
  1347.     rc = ttol((CHAR *)str_request, i);
  1348. #ifdef OS2
  1349.     ReleaseTelnetMutex();
  1350. #endif
  1351.     if ( rc == i )
  1352.         return(0);
  1353.     else
  1354.         return(-1);
  1355. }
  1356.  
  1357. #ifdef CK_ENCRYPTION
  1358. VOID
  1359. ck_tn_enc_start()
  1360. {
  1361.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1362.         return;
  1363.     if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
  1364.          (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
  1365.         debug(F110,"ck_tn_enc_start","nothing to do",0);
  1366.         return;
  1367.     }
  1368.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1369.     if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
  1370.         debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
  1371.         encrypt_request_start();
  1372.     }
  1373.     if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
  1374.         debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
  1375.         encrypt_send_request_start();
  1376.     }
  1377.     tn_wait("encrypt start");
  1378.     tn_push();
  1379. }
  1380.  
  1381. VOID
  1382. ck_tn_enc_stop()
  1383. {
  1384.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1385.         return;
  1386.     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
  1387.          !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
  1388.         debug(F110,"ck_tn_enc_stop","nothing to do",0);
  1389.       return;
  1390.     }
  1391.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1392.     if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
  1393.         debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
  1394.         encrypt_send_request_end();
  1395.     }
  1396.     if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
  1397.         debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
  1398.         encrypt_send_end();
  1399.     }
  1400.     tn_wait("encrypt stop");
  1401.     tn_push();
  1402. }
  1403. #endif /* CK_ENCRYPTION */
  1404.  
  1405. /*  C K _ K R B _ T N _ S B _ A U T H
  1406.  *  An interface between the C-Kermit Telnet Command Parser and the Authent-
  1407.  *  ication option parser implemented in the Kerberos Telnet client.
  1408.  *
  1409.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1410.  *  len  - the length of the buffer
  1411.  *
  1412.  *  Returns: 0 on success and -1 on failure
  1413.  */
  1414.  
  1415. int
  1416. #ifdef CK_ANSIC
  1417. ck_tn_sb_auth(char * sb, int len)
  1418. #else /* CK_ANSIC */
  1419. ck_tn_sb_auth(sb,len) char * sb; int len;
  1420. #endif /* CK_ANSIC */
  1421. {
  1422.     /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1423.     /* and it wants the length to exclude the IAC SE bytes               */
  1424.     CHAR * buf;
  1425.     int rc = -1;
  1426.  
  1427.     buf = malloc(len-1);
  1428.     if ( !buf ) return(-1);
  1429.  
  1430.     buf[0] = SB;
  1431.     memcpy( &buf[1], sb, len-2 );
  1432.     rc = auth_parse(buf,len-1);
  1433.     free(buf);
  1434.     debug(F111,"ck_tn_sb_auth","rc",rc);
  1435.     if (rc == AUTH_FAILURE) {
  1436.         authentication_version = AUTHTYPE_NULL;
  1437. #ifndef NOLOCAL
  1438. #ifdef OS2
  1439.         ipadl25();
  1440. #endif /* OS2 */
  1441. #endif /* NOLOCAL */
  1442.         return(-1);
  1443.     }
  1444. #ifndef NOLOCAL
  1445. #ifdef OS2
  1446.     ipadl25();
  1447. #endif /* OS2 */
  1448. #endif /* NOLOCAL */
  1449.     return(0);
  1450. }
  1451.  
  1452. /*  C K _ K R B _ T N _ S B _ E N C R Y P T
  1453.  *  An interface between the C-Kermit Telnet Command Parser and the Encryption
  1454.  *  option parser implemented in the Kerberos Telnet client.
  1455.  *
  1456.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1457.  *  len  - the length of the buffer
  1458.  *
  1459.  *  Returns: Always returns 0 for success since encrypt_parse is void
  1460.  */
  1461.  
  1462.  
  1463. int
  1464. #ifdef CK_ANSIC
  1465. ck_tn_sb_encrypt(char * sb, int len)
  1466. #else
  1467. ck_tn_sb_encrypt(sb,len) char * sb; int len;
  1468. #endif /* CK_ANSIC */
  1469. {
  1470.     /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1471.     /* and it wants the length to exclude the IAC SE bytes                  */
  1472. #ifdef CK_ENCRYPTION
  1473.     char * buf;
  1474.     int rc = -1;
  1475.  
  1476.     buf = malloc(len-1);
  1477.     if ( !buf ) return(-1);
  1478.  
  1479.     buf[0] = SB;
  1480.     memcpy( &buf[1], sb, len-2 );
  1481.     rc = encrypt_parse((CHAR *)buf,len-1);
  1482.  
  1483.     if (rc < 0) {
  1484.         free(buf);
  1485.         return(-1);
  1486.     }
  1487.  
  1488.     /* This is a hack.  It does not belong here but should really be in */
  1489.     /* encrypt_parse() but in K95 the encrypt_parse() routine does not  */
  1490.     /* have access to the telopt_states array.                          */
  1491.     if ( buf[1] == ENCRYPT_REQEND )
  1492.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1493.     else if ( buf[1] == ENCRYPT_REQSTART )
  1494.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1495. #ifndef NOLOCAL
  1496. #ifdef OS2
  1497.     ipadl25();
  1498. #endif /* OS2 */
  1499. #endif /* NOLOCAL */
  1500.     free(buf);
  1501. #endif /* ENCRYPTION */
  1502.     return(0);
  1503. }
  1504.  
  1505.  
  1506. /*  C K _ K R B _ E N C R Y P T I N G
  1507.  *  Returns 1 if we are encrypting and 0 if we are not
  1508.  */
  1509.  
  1510. int
  1511. #ifdef CK_ANSIC
  1512. ck_tn_encrypting(VOID)
  1513. #else /* CK_ANSIC */
  1514. ck_tn_encrypting()
  1515. #endif /* CK_ANSIC */
  1516. {
  1517. #ifdef CK_ENCRYPTION
  1518.     if ( g_kstream == NULL )
  1519.         return(0);
  1520.     if ( g_kstream->encrypt && encrypt_is_encrypting()) {
  1521.         debug(F111,"ck_tn_encrypting","encrypting",
  1522.                g_kstream->encrypt_type);
  1523.         return(g_kstream->encrypt_type);
  1524.     }
  1525. #endif /* CK_ENCRYPTION */
  1526.     debug(F110,"ck_tn_encrypting","not encrypting",0);
  1527.     return(0);
  1528. }
  1529.  
  1530. /*  C K _ K R B _ D E C R Y P T I N G
  1531.  *  Returns 1 if we are decrypting and 0 if we are not
  1532.  */
  1533.  
  1534. int
  1535. #ifdef CK_ANSIC
  1536. ck_tn_decrypting(VOID)
  1537. #else
  1538. ck_tn_decrypting()
  1539. #endif /* CK_ANSIC */
  1540. {
  1541. #ifdef CK_ENCRYPTION
  1542.     if ( g_kstream == NULL )
  1543.         return(0);
  1544.     if ( g_kstream->decrypt && encrypt_is_decrypting()) {
  1545.         debug(F111,"ck_tn_decrypting","decrypting",
  1546.                g_kstream->decrypt_type);
  1547.         return(g_kstream->decrypt_type);
  1548.     }
  1549. #endif /* CK_ENCRYPTION */
  1550.     debug(F110,"ck_tn_decrypting","not decrypting",0);
  1551.     return(0);
  1552. }
  1553.  
  1554. /*  C K _ K R B _ A U T H E N T I C A T E D
  1555.  *  Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
  1556.  *  or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
  1557.  */
  1558.  
  1559. int
  1560. #ifdef CK_ANSIC
  1561. ck_tn_authenticated(VOID)
  1562. #else
  1563. ck_tn_authenticated()
  1564. #endif
  1565. {
  1566.     return(authentication_version);
  1567. }
  1568.  
  1569. /*  C K _ K R B _ E N C R Y P T
  1570.  *  encrypts n characters in s if we are encrypting
  1571.  */
  1572.  
  1573. VOID
  1574. #ifdef CK_ANSIC
  1575. ck_tn_encrypt( char * s, int n )
  1576. #else
  1577. ck_tn_encrypt( s,n ) char * s; int n;
  1578. #endif
  1579. {
  1580. #ifdef CK_ENCRYPTION
  1581.     struct kstream_data_block i;
  1582.  
  1583.     if (g_kstream->encrypt && encrypt_is_encrypting()) {
  1584. #ifdef DEBUG
  1585.       ckhexdump("from plaintext", s, n);
  1586. #endif
  1587.         i.ptr = s;
  1588.         i.length = n;
  1589.         g_kstream->encrypt(&i, NULL);
  1590. #ifdef DEBUG
  1591.         ckhexdump("to cyphertext", s, n);
  1592. #endif
  1593.     }
  1594.     else debug(F101,"ck_tn_encrypt not encrypting","",n);
  1595. #endif /* ENCRYPTION */
  1596. }
  1597.  
  1598. /*  C K _ K R B _ D E C R Y P T
  1599.  *  decrypts n characters in s if we are decrypting
  1600.  */
  1601.  
  1602. VOID
  1603. #ifdef CK_ANSIC
  1604. ck_tn_decrypt( char * s, int n )
  1605. #else
  1606. ck_tn_decrypt( s,n ) char * s; int n;
  1607. #endif
  1608. {
  1609. #ifdef CK_ENCRYPTION
  1610.     struct kstream_data_block i;
  1611.  
  1612.     if (g_kstream->decrypt && encrypt_is_decrypting()) {
  1613.  
  1614. #ifdef DEBUG
  1615.         ckhexdump("from cyphertext", s, n);
  1616. #endif
  1617.  
  1618.         i.ptr = s;
  1619.         i.length = n;
  1620.         g_kstream->decrypt(&i, NULL);
  1621. #ifdef DEBUG
  1622.         ckhexdump("to plaintext", s, n);
  1623. #endif
  1624.     }
  1625.     else debug(F101,"ck_tn_decrypt not decrypting","",n);
  1626. #endif /* ENCRYPTION */
  1627. }
  1628.  
  1629. /*  S E N D K 5 A U T H S B
  1630.  *  Send a Kerberos 5 Authentication Subnegotiation to host and
  1631.  *  output appropriate Telnet Debug messages
  1632.  *
  1633.  *  type - Sub Negotiation type
  1634.  *  data - ptr to buffer containing data
  1635.  *  len  - len of buffer if not NUL terminated
  1636.  *
  1637.  *  returns number of characters sent or error value
  1638.  */
  1639.  
  1640. static int
  1641. #ifdef CK_ANSIC
  1642. SendK5AuthSB(int type, void *data, int len)
  1643. #else
  1644. SendK5AuthSB(type,data,len) int type; void *data; int len;
  1645. #endif
  1646. {
  1647.     int rc;
  1648.     unsigned char *p = str_data + 3;
  1649.     unsigned char *cd = (unsigned char *)data;
  1650.     extern int sstelnet;
  1651.  
  1652. #ifdef CK_SSL
  1653.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1654.         if (ttchk() < 0)
  1655.           return(0);
  1656.         else
  1657.           return(1);
  1658.     }
  1659. #endif /* CK_SSL */
  1660.  
  1661.     if ( type < 0 || type > 7 )         /* Check for invalid values */
  1662.         return(0);
  1663.  
  1664.     if (!cd) {
  1665.         cd = (unsigned char *)"";
  1666.         len = 0;
  1667.     }
  1668.  
  1669.     if (len == -1)                        /* Use strlen() for len */
  1670.         len = strlen((char *)cd);
  1671.  
  1672.     /* Construct Message */
  1673.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1674.     *p++ = AUTHTYPE_KERBEROS_V5;
  1675.     *p = AUTH_CLIENT_TO_SERVER;
  1676.     *p |= auth_how;
  1677. #ifdef CK_ENCRYPTION
  1678.     *p |= auth_crypt;
  1679. #endif
  1680. #ifdef USE_INI_CRED_FWD
  1681.     if (auth_fwd)
  1682.         *p |= INI_CRED_FWD_ON;
  1683. #endif /* USE_INI_CRED_FWD */
  1684.     p++;
  1685.     *p++ = type;
  1686.     while (len-- > 0) {
  1687.         if ((*p++ = *cd++) == IAC)
  1688.             *p++ = IAC;
  1689.     }
  1690.     *p++ = IAC;
  1691.     *p++ = SE;
  1692.  
  1693.     /* Handle Telnet Debugging Messages */
  1694.     if (deblog || tn_deb || debses) {
  1695.         int i;
  1696.         int deblen=p-str_data-2;
  1697.         char *s=NULL;
  1698.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1699.             auth_crypt
  1700. #ifdef USE_INI_CRED_FWD
  1701.               | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  1702. #endif /* USE_INI_CRED_FWD */
  1703.                     ;
  1704.  
  1705.         switch (type) {
  1706.         case 0:
  1707.             s = "AUTH";
  1708.             break;
  1709.         case 1:
  1710.             s = "REJECT";
  1711.             break;
  1712.         case 2:
  1713.             s = "ACCEPT";
  1714.             break;
  1715.         case 3:
  1716.             s = "RESPONSE";
  1717.             break;
  1718.         case 4:
  1719.             s = "FORWARD";
  1720.             break;
  1721.         case 5:
  1722.             s = "FORWARD_ACCEPT";
  1723.             break;
  1724.         case 6:
  1725.             s = "FORWARD_REJECT";
  1726.             break;
  1727.         case 7:
  1728.             s = "TLS_VERIFY";
  1729.                 break;
  1730.         }
  1731.  
  1732.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  1733.                   "TELNET SENT SB ",
  1734.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1735.                  str_data[3] == TELQUAL_IS ? "IS" :
  1736.                  str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ",
  1737.                  AUTHTYPE_NAME(authentication_version)," ",
  1738.                  AUTHMODE_NAME(mode)," ",
  1739.                  s," ",NULL);
  1740.         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1741.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1742.         debug(F100,tn_msg,"",0);
  1743.         if (tn_deb || debses) tn_debug(tn_msg);
  1744.     }
  1745.  
  1746.     /* Send data */
  1747. #ifdef OS2
  1748.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1749. #endif
  1750.     rc = ttol((CHAR *)str_data, p - str_data);
  1751. #ifdef OS2
  1752.     ReleaseTelnetMutex();
  1753. #endif
  1754.     debug(F111,"SendK5AuthSB","ttol()",rc);
  1755.     return(rc);
  1756. }
  1757.  
  1758. /*  S E N D K 4 A U T H S B
  1759.  *  Send a Kerberos 4 Authentication Subnegotiation to host and
  1760.  *  output appropriate Telnet Debug messages
  1761.  *
  1762.  *  type - Sub Negotiation type
  1763.  *  data - ptr to buffer containing data
  1764.  *  len  - len of buffer if not NUL terminated
  1765.  *
  1766.  *  returns number of characters sent or error value
  1767.  */
  1768.  
  1769. static int
  1770. #ifdef CK_ANSIC
  1771. SendK4AuthSB(int type, void *data, int len)
  1772. #else
  1773. SendK4AuthSB(type,data,len) int type; void *data; int len;
  1774. #endif
  1775. {
  1776.     int rc;
  1777.     unsigned char *p = str_data + 3;
  1778.     unsigned char *cd = (unsigned char *)data;
  1779.     extern int sstelnet;
  1780.     int mode = (auth_how & AUTH_HOW_MASK) |
  1781.         auth_crypt;
  1782.  
  1783.     if ( type < 0 || type > 4 )         /* Check for invalid values */
  1784.         return(0);
  1785.  
  1786. #ifdef CK_SSL
  1787.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1788.         if (ttchk() < 0)
  1789.           return(0);
  1790.         else
  1791.           return(1);
  1792.     }
  1793. #endif /* CK_SSL */
  1794.  
  1795.     if (!cd) {
  1796.         cd = (unsigned char *)"";
  1797.         len = 0;
  1798.     }
  1799.  
  1800.     if (len == -1)                        /* Use strlen() for len */
  1801.         len = strlen((char *)cd);
  1802.  
  1803.  
  1804.     /* Construct Message */
  1805.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1806.     *p++ = AUTHTYPE_KERBEROS_V4;
  1807.     *p = AUTH_CLIENT_TO_SERVER;
  1808.     *p |= mode;
  1809.     p++;
  1810.     *p++ = type;
  1811.     while (len-- > 0) {
  1812.         if ((*p++ = *cd++) == IAC)
  1813.             *p++ = IAC;
  1814.         }
  1815.     *p++ = IAC;
  1816.     *p++ = SE;
  1817.  
  1818.     /* Handle Telnet Debugging Messages */
  1819.     if (deblog || tn_deb || debses) {
  1820.         int i;
  1821.         int deblen=p-str_data-2;
  1822.         char *s=NULL;
  1823.  
  1824.         switch (type) {
  1825.         case 0:
  1826.             s = "AUTH";
  1827.             break;
  1828.         case 1:
  1829.             s = "REJECT";
  1830.             break;
  1831.         case 2:
  1832.             s = "ACCEPT";
  1833.             break;
  1834.         case 3:
  1835.             s = "CHALLENGE";
  1836.             break;
  1837.         case 4:
  1838.             s = "RESPONSE";
  1839.             break;
  1840.         }
  1841.  
  1842.         ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ",
  1843.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1844.                  str_data[3] == TELQUAL_IS ? "IS" :
  1845.                  (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ",
  1846.                  AUTHTYPE_NAME(authentication_version)," ",
  1847.                  AUTHMODE_NAME(mode)," ",
  1848.                  s," ",NULL);
  1849.         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1850.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1851.         debug(F100,tn_msg,"",0);
  1852.         if (tn_deb || debses) tn_debug(tn_msg);
  1853.     }
  1854.  
  1855.     /* Send data */
  1856. #ifdef OS2
  1857.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1858. #endif
  1859.     rc = ttol((CHAR *)str_data, p - str_data);
  1860. #ifdef OS2
  1861.     ReleaseTelnetMutex();
  1862. #endif
  1863.     debug(F111,"SendK4AuthSB","ttol()",rc);
  1864.     return(rc);
  1865. }
  1866.  
  1867. /*  S E N D S R P A U T H S B
  1868.  *  Send a SRP Authentication Subnegotiation to host and
  1869.  *  output appropriate Telnet Debug messages
  1870.  *
  1871.  *  type - Sub Negotiation type
  1872.  *  data - ptr to buffer containing data
  1873.  *  len  - len of buffer if not NUL terminated
  1874.  *
  1875.  *  returns number of characters sent or error value
  1876.  */
  1877.  
  1878. static int
  1879. #ifdef CK_ANSIC
  1880. SendSRPAuthSB(int type, void *data, int len)
  1881. #else
  1882. SendSRPAuthSB(type,data,len) int type; void *data; int len;
  1883. #endif
  1884. {
  1885.     int rc;
  1886.     unsigned char *p = str_data + 3;
  1887.     unsigned char *cd = (unsigned char *)data;
  1888.     extern int sstelnet;
  1889.  
  1890.     /* Check for invalid values */
  1891.     if ( type != SRP_EXP && type != SRP_RESPONSE &&
  1892.          type != SRP_REJECT && type != SRP_ACCEPT &&
  1893.          type != SRP_CHALLENGE && type != SRP_PARAMS &&
  1894.          type != SRP_AUTH)
  1895.         return(0);
  1896.  
  1897.     if (len == -1)                        /* Use strlen() for len */
  1898.         len = strlen((char *)cd);
  1899.  
  1900.     /* Construct Message */
  1901.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1902.     *p++ = AUTHTYPE_SRP;
  1903.     *p = AUTH_CLIENT_TO_SERVER;
  1904.     *p |= auth_how;
  1905. #ifdef CK_ENCRYPTION
  1906.     *p |= auth_crypt;
  1907. #endif
  1908.     p++;
  1909.     *p++ = type;
  1910.     while (len-- > 0) {
  1911.         if ((*p++ = *cd++) == IAC)
  1912.             *p++ = IAC;
  1913.         }
  1914.     *p++ = IAC;
  1915.     *p++ = SE;
  1916.  
  1917.     /* Handle Telnet Debugging Messages */
  1918.     if (deblog || tn_deb || debses) {
  1919.         int i;
  1920.         int deblen=p-str_data-2;
  1921.         char *s=NULL;
  1922.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1923.             auth_crypt;
  1924.  
  1925.         switch (type) {
  1926.         case 0:
  1927.             s = "AUTH";
  1928.             break;
  1929.         case 1:
  1930.             s = "REJECT";
  1931.             break;
  1932.         case 2:
  1933.             s = "ACCEPT";
  1934.             break;
  1935.         case 3:
  1936.             s = "CHALLENGE";
  1937.             break;
  1938.         case 4:
  1939.             s = "RESPONSE";
  1940.             break;
  1941.         case 5:
  1942.             s = "FORWARD";
  1943.             break;
  1944.         case 6:
  1945.             s = "FORWARD_ACCEPT";
  1946.             break;
  1947.         case 7:
  1948.             s = "FORWARD_REJECT";
  1949.             break;
  1950.         case 8:
  1951.             s = "EXP";
  1952.             break;
  1953.         case 9:
  1954.             s = "PARAMS";
  1955.             break;
  1956.         }
  1957.  
  1958.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  1959.                   "TELNET SENT SB ",
  1960.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1961.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  1962.                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
  1963.                  AUTHTYPE_NAME(authentication_version)," ",
  1964.                  AUTHMODE_NAME(mode)," ",
  1965.                  s," ",NULL);
  1966.         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1967.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1968.         debug(F100,tn_msg,"",0);
  1969.         if (tn_deb || debses) tn_debug(tn_msg);
  1970.     }
  1971.  
  1972.     /* Send data */
  1973. #ifdef OS2
  1974.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1975. #endif
  1976.     rc = ttol((CHAR *)str_data, p - str_data);
  1977. #ifdef OS2
  1978.     ReleaseTelnetMutex();
  1979. #endif
  1980.     return(rc);
  1981. }
  1982.  
  1983. #ifdef CK_ENCRYPTION
  1984. /*
  1985.  * Function: Enable or disable the encryption process.
  1986.  *
  1987.  * Parameters:
  1988.  *      enable - TRUE to enable, FALSE to disable.
  1989.  */
  1990. static VOID
  1991. #ifdef CK_ANSIC
  1992. auth_encrypt_enable(BOOL enable)
  1993. #else
  1994. auth_encrypt_enable(enable) BOOL enable;
  1995. #endif
  1996. {
  1997.   encrypt_flag = enable;
  1998. }
  1999. #endif
  2000.  
  2001. /*
  2002.  * Function: Abort the authentication process
  2003.  *
  2004.  * Parameters:
  2005.  */
  2006. static VOID
  2007. #ifdef CK_ANSIC
  2008. auth_abort(char *errmsg, long r)
  2009. #else
  2010. auth_abort(errmsg,r) char *errmsg; long r;
  2011. #endif
  2012. {
  2013.     char buf[9];
  2014.     extern int sstelnet;
  2015.  
  2016. #ifdef CK_SSL
  2017.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  2018.         return;
  2019.     }
  2020. #endif /* CK_SSL */
  2021.     debug(F111,"auth_abort",errmsg,r);
  2022.  
  2023.     /* Construct Telnet Debugging messages */
  2024.     if (deblog || tn_deb || debses) {
  2025.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  2026.                   "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2027.                   " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ",
  2028.                    AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE",
  2029.                    NULL,NULL,NULL,NULL,NULL
  2030.                  );
  2031.         debug(F100,tn_msg,"",0);
  2032.         if (tn_deb || debses) tn_debug(tn_msg);
  2033.     }
  2034.  
  2035.     /* Construct the Abort message to send to the host   */
  2036.     /* Basicly we change the authentication type to NULL */
  2037.     sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  2038.              sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
  2039.              AUTHTYPE_NULL, IAC, SE);   /* safe */
  2040. #ifdef OS2
  2041.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2042. #endif
  2043.     ttol((CHAR *)buf, 8);
  2044. #ifdef OS2
  2045.     ReleaseTelnetMutex();
  2046. #endif
  2047.  
  2048.     /* If there is an error message, and error number construct */
  2049.     /* an explanation to display to the user                    */
  2050.     if (errmsg != NULL) {
  2051.         ckstrncpy(strTmp, errmsg, AUTHTMPBL);
  2052.     } else
  2053.         strTmp[0] = '\0';
  2054.  
  2055.  
  2056.     if (r != AUTH_SUCCESS) {
  2057.         ckstrncat(strTmp, "\r\n",AUTHTMPBL);
  2058. #ifdef KRB4
  2059.         if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
  2060.             ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),
  2061.                        AUTHTMPBL);
  2062.             debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
  2063.         }
  2064. #endif
  2065. #ifdef KRB5
  2066.         if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
  2067.             ckstrncat(strTmp, error_message(r),AUTHTMPBL);
  2068.             debug(F111,"auth_abort",error_message(r),r);
  2069.         }
  2070. #endif
  2071.     }
  2072.     printf("Authentication failed: %s\r\n",strTmp);
  2073. #ifdef CKSYSLOG
  2074.     if (ckxsyslog >= SYSLG_LI && ckxlogging) {
  2075.         cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
  2076.                   (char *) szUserNameRequested,
  2077.                   strTmp);
  2078.     }
  2079. #endif /* CKSYSLOG */
  2080.     authentication_version = AUTHTYPE_NULL;
  2081. }
  2082.  
  2083.  
  2084. /*
  2085.  * Function: Copy data to buffer, doubling IAC character if present.
  2086.  *
  2087.  */
  2088. int
  2089. #ifdef CK_ANSIC
  2090. copy_for_net(unsigned char *to, unsigned char *from, int c)
  2091. #else
  2092. copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
  2093. #endif
  2094. {
  2095.     int n;
  2096.  
  2097.     n = c;
  2098.     debug(F111,"copy_for_net","before",n);
  2099.     while (c-- > 0) {
  2100.         if ((*to++ = *from++) == IAC) {
  2101.             n++;
  2102.             *to++ = IAC;
  2103.         }
  2104.     }
  2105.     debug(F111,"copy_for_net","after",n);
  2106.     return n;
  2107. }
  2108.  
  2109. #ifdef CK_SSL
  2110. /*  S E N D S S L A U T H S B
  2111.  *  Send a SSL Authentication Subnegotiation to host and
  2112.  *  output appropriate Telnet Debug messages
  2113.  *
  2114.  *  type - Sub Negotiation type
  2115.  *  data - ptr to buffer containing data
  2116.  *  len  - len of buffer if not NUL terminated
  2117.  *
  2118.  *  returns number of characters sent or error value
  2119.  */
  2120.  
  2121. int
  2122. #ifdef CK_ANSIC
  2123. SendSSLAuthSB(int type, void *data, int len)
  2124. #else
  2125. SendSSLAuthSB(type,data,len) int type; void *data; int len;
  2126. #endif
  2127. {
  2128.     int rc;
  2129.     unsigned char *p = str_data + 3;
  2130.     unsigned char *cd = (unsigned char *)data;
  2131.     extern int sstelnet;
  2132.  
  2133.     /* Check for invalid values */
  2134.     if ( type != SSL_START && type != SSL_ACCEPT &&
  2135.          type != SSL_REJECT)
  2136.         return(0);
  2137.  
  2138.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  2139.         if (ttchk() < 0)
  2140.           return(0);
  2141.         else
  2142.           return(1);
  2143.     }
  2144.  
  2145.     if (len == -1)                        /* Use strlen() for len */
  2146.         len = strlen((char *)cd);
  2147.  
  2148.     /* Construct Message */
  2149.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  2150.     *p++ = AUTHTYPE_SSL;
  2151.     *p = AUTH_CLIENT_TO_SERVER;
  2152.     *p |= auth_how;
  2153. #ifdef CK_ENCRYPTION
  2154.     *p |= auth_crypt;
  2155. #endif
  2156.     p++;
  2157.     *p++ = type;
  2158.     while (len-- > 0) {
  2159.         if ((*p++ = *cd++) == IAC)
  2160.             *p++ = IAC;
  2161.         }
  2162.     *p++ = IAC;
  2163.     *p++ = SE;
  2164.  
  2165.     /* Handle Telnet Debugging Messages */
  2166.     if (deblog || tn_deb || debses) {
  2167.         int i;
  2168.         int deblen=p-str_data-2;
  2169.         char *s=NULL;
  2170.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  2171.             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
  2172.  
  2173.         switch (type) {
  2174.         case SSL_START:
  2175.             s = "START";
  2176.             break;
  2177.         case SSL_ACCEPT:
  2178.             s = "ACCEPT";
  2179.             break;
  2180.         case SSL_REJECT:
  2181.             s = "REJECT";
  2182.             break;
  2183.         }
  2184.  
  2185.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  2186.                   "TELNET SENT SB ",
  2187.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  2188.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  2189.                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
  2190.                  AUTHTYPE_NAME(authentication_version)," ",
  2191.                  AUTHMODE_NAME(mode)," ",
  2192.                  s," ",NULL);
  2193.         tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  2194.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  2195.         debug(F100,tn_msg,"",0);
  2196.         if (tn_deb || debses) tn_debug(tn_msg);
  2197.     }
  2198.  
  2199.     /* Send data */
  2200. #ifdef OS2
  2201.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2202. #endif
  2203.     rc = ttol((CHAR *)str_data, p - str_data);
  2204. #ifdef OS2
  2205.     ReleaseTelnetMutex();
  2206. #endif
  2207.     return(rc);
  2208. }
  2209. #endif  /* CK_SSL */
  2210.  
  2211. int
  2212. tn_how_ok(int how)
  2213. {
  2214.     switch ( tn_auth_how ) {
  2215.     case TN_AUTH_HOW_ANY:
  2216.         return(1);
  2217.     case TN_AUTH_HOW_ONE_WAY:
  2218.         return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
  2219.     case TN_AUTH_HOW_MUTUAL:
  2220.         return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
  2221.     default:
  2222.         return(0);
  2223.     }
  2224. }
  2225.  
  2226. int
  2227. tn_enc_ok(int enc)
  2228. {
  2229.     switch ( tn_auth_enc ) {
  2230.     case TN_AUTH_ENC_ANY:
  2231.         if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
  2232.             (!ck_ssleay_is_installed()
  2233. #ifdef CK_SSL
  2234.              || !ssl_finished_messages ||
  2235.              !(tls_active_flag || ssl_active_flag)
  2236. #endif /* CK_SSL */
  2237.              )) {
  2238. #ifdef CK_SSL
  2239.             if (!ssl_finished_messages)
  2240.                 debug(F100,"tn_enc_ok !ssl_finished_messages","",0);
  2241. #endif /* CK_SSL */
  2242.             return(0);
  2243.         }
  2244.         return(1);
  2245.     case TN_AUTH_ENC_NONE:
  2246.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
  2247.     case TN_AUTH_ENC_TELOPT:
  2248.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
  2249.     case TN_AUTH_ENC_EXCH:
  2250.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
  2251.     case TN_AUTH_ENC_TLS:
  2252.         return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) &&
  2253.                ck_ssleay_is_installed()
  2254. #ifdef CK_SSL
  2255.                && ssl_finished_messages &&
  2256.                (tls_active_flag || ssl_active_flag)
  2257. #endif /* CK_SSL */
  2258.            );
  2259.     default:
  2260.         return(0);
  2261.     }
  2262. }
  2263.  
  2264. static int
  2265. atok(int at) {
  2266.     int i;
  2267.     if ( auth_type_user[0] == AUTHTYPE_AUTO )
  2268.         return(1);
  2269.     if ( auth_type_user[0] == AUTHTYPE_NULL )
  2270.         return(0);
  2271.  
  2272.     for ( i=0;
  2273.           i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
  2274.           i++ ) {
  2275.         if ( auth_type_user[i] == at )
  2276.             return(1);
  2277.     }
  2278.  
  2279.     return(0);
  2280. }
  2281.  
  2282.  
  2283. /*
  2284.  * Function: Parse authentication send command
  2285.  *
  2286.  * Parameters:
  2287.  *  parsedat - the sub-command data.
  2288.  *
  2289.  *      end_sub - index of the character in the 'parsedat' array which
  2290.  *              is the last byte in a sub-negotiation
  2291.  *
  2292.  * Returns: Kerberos error code.
  2293.  */
  2294.  
  2295. static unsigned char send_list[512];
  2296. static int  send_len = 0;
  2297.  
  2298. _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub));
  2299.  
  2300. static int
  2301. #ifdef CK_ANSIC
  2302. auth_resend(int type)
  2303. #else
  2304. auth_resend(type) int type;
  2305. #endif /* CK_ANSIC */
  2306. {
  2307.     int i=2;
  2308.     while (i+1 <= send_len) {
  2309.         if (send_list[i] == type) {
  2310.             int j;
  2311.             send_len -= 2;
  2312.             for (j = i; j < send_len; j++)
  2313.                 send_list[j] = send_list[j+2];
  2314.         } else {
  2315.             i += 2;
  2316.         }
  2317.     }
  2318.     return(auth_send(send_list,send_len));
  2319. }
  2320.  
  2321. static int
  2322. #ifdef CK_ANSIC
  2323. auth_send(unsigned char *parsedat, int end_sub)
  2324. #else
  2325. auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  2326. #endif
  2327. {
  2328.     static unsigned char buf[4096];
  2329.     unsigned char *pname;
  2330.     int plen;
  2331.     int r;
  2332.     int i;
  2333.     int mode;
  2334. #ifdef MIT_CURRENT
  2335. #ifdef CK_ENCRYPTION
  2336.     krb5_data data;
  2337.     krb5_enc_data encdata;
  2338.     krb5_error_code code;
  2339.     krb5_keyblock random_key;
  2340. #endif /* ENCRYPTION */
  2341. #endif /* MIT_CURRENT */
  2342. #ifdef KRB5
  2343.     int krb5_msg = 0;
  2344. #endif /* KRB5 */
  2345. #ifdef KRB4
  2346.     int krb4_msg = 0;
  2347. #endif /* KRB4 */
  2348. #ifdef GSSAPI_KRB5
  2349.     int gssk5_msg = 0;
  2350. #endif /* GSSAPI_KRB5 */
  2351.     int iaccnt=0;
  2352.  
  2353. #ifdef CK_SSL
  2354.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  2355.         return(AUTH_SUCCESS);
  2356. #endif /* CK_SSL */
  2357.  
  2358.     auth_how = -1;              /* We have not found an auth method  */
  2359.     auth_crypt = 0;             /* We are not using encryption (yet) */
  2360.     send_len = end_sub > 512 ? 512 : end_sub;
  2361.     memcpy(send_list,parsedat,send_len);
  2362.  
  2363.     /* Search the list of acceptable Authentication types sent from */
  2364.     /* the host and find one that we support                        */
  2365.  
  2366.     /* For Kerberos authentications, try to determine if we have a  */
  2367.     /* valid TGT, if not skip over the authentication type because  */
  2368.     /* we wouldn't be able to successfully login anyway.  Perhaps   */
  2369.     /* there is another supported authentication which we could use */
  2370.  
  2371. #ifdef NO_FTP_AUTH
  2372.     /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
  2373.     /* for Kerberos or SRP.                                         */
  2374. #endif /* NO_FTP_AUTH */
  2375.  
  2376.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  2377.     for (i = 2; i+1 <= end_sub; i += 2) {
  2378. #ifdef NTLM
  2379.         if (parsedat[i] == AUTHTYPE_NTLM &&
  2380.              ck_ntlm_is_valid(1) &&
  2381.              ntlm_auth_send() == 0) {
  2382.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2383.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2384. #ifdef CK_ENCRYPTION
  2385.                 /* NTLM does not support Telnet Encryption */
  2386.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2387.                     continue;
  2388.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2389. #endif /* CK_ENCRYPTION */
  2390.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2391.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2392.                 authentication_version = AUTHTYPE_NTLM;
  2393.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2394.                 break;
  2395.             }
  2396.         }
  2397. #endif /* NTLM */
  2398. #ifdef CK_SSL
  2399.         if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
  2400. #ifdef SSLDLL
  2401.              ck_ssleay_is_installed() &&
  2402. #endif /* SSLDLL */
  2403.              !tls_active_flag && !ssl_active_flag
  2404. #ifndef USE_CERT_CB
  2405.              && tls_load_certs(ssl_ctx,ssl_con,0)
  2406. #endif /* USE_CERT_CB */
  2407.              ) {
  2408.  
  2409.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2410.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2411. #ifdef CK_ENCRYPTION
  2412.                 /* SSL does not support Telnet Encryption */
  2413.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2414.                     continue;
  2415.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2416. #endif /* CK_ENCRYPTION */
  2417.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2418.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2419.                 authentication_version = AUTHTYPE_SSL;
  2420.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2421.                 break;
  2422.             }
  2423.         }
  2424. #endif /* SSL */
  2425. #ifdef CK_SRP
  2426.         if ( parsedat[i] == AUTHTYPE_SRP
  2427. #ifdef SRPDLL
  2428.              && hSRP
  2429. #endif /* SRPDLL */
  2430. #ifdef NO_FTP_AUTH
  2431.              && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2432. #endif /* NO_FTP_AUTH */
  2433.              ) {
  2434.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2435.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2436. #ifdef PRE_SRP_1_4_5
  2437.                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2438.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2439.                     continue;
  2440. #endif /* PRE_SRP_1_4_5 */
  2441.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2442.                      AUTH_ENCRYPT_USING_TELOPT) &&
  2443.                     (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2444.                      TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2445.                     continue;
  2446.  
  2447.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2448. #ifdef CK_ENCRYPTION
  2449.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2450.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2451.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2452.                 }
  2453. #endif /* CK_ENCRYPTION */
  2454. #ifdef CK_SSL
  2455.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2456.                      ck_ssleay_is_installed() &&
  2457.                      (tls_active_flag || ssl_active_flag) ) {
  2458.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2459.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2460.                 }
  2461. #endif /* CK_SSL */
  2462.                 authentication_version = AUTHTYPE_SRP;
  2463.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2464.                 break;
  2465.             }
  2466.         }
  2467. #endif /* SRP */
  2468. #ifdef GSSAPI_KRB5
  2469.         if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
  2470.             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2471.             AUTH_ENCRYPT_AFTER_EXCHANGE &&
  2472. #ifdef OS2
  2473.             hGSSAPI &&
  2474. #endif /* OS2 */
  2475. #ifdef NO_FTP_AUTH
  2476.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2477. #endif /* NO_FTP_AUTH */
  2478.              ck_gssapi_is_installed() && !gssk5_msg)
  2479.         {
  2480.             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2481.                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2482.                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
  2483.             {
  2484.                 /* If we are auto-getting TGTs, try */
  2485.                 if ( !ck_krb5_is_tgt_valid() ) {
  2486.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2487.                 }
  2488.                 gssk5_msg = 1;
  2489.             }
  2490.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2491.                       AUTH_CLIENT_TO_SERVER &&
  2492.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2493.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2494. #ifdef CK_ENCRYPTION
  2495.                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
  2496.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2497.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2498.                 }
  2499. #endif /* CK_ENCRYPTION */
  2500.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2501.                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
  2502.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2503.                 break;
  2504.             }
  2505.         }
  2506. #endif /* GSSAPI_KRB5 */
  2507. #ifdef KRB5
  2508.         if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2509. #ifdef OS2
  2510.              hKRB5_32 &&
  2511. #endif /* OS2 */
  2512. #ifdef NO_FTP_AUTH
  2513.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2514. #endif /* NO_FTP_AUTH */
  2515.              ck_krb5_is_installed() && !krb5_msg) {
  2516.  
  2517.             /* Without encryption we can't perform mutual authentication */
  2518.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2519.                  !ck_crypt_is_installed())
  2520.                 continue;
  2521.  
  2522.             /* Skip over entries that request credential forwarding */
  2523.             /* if we are not forwarding.                            */
  2524.             if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2525.                 (forward_flag &&
  2526.                   ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2527.                 continue;
  2528.  
  2529.             if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2530.                                 parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2531.                                 parsedat[i+1] & INI_CRED_FWD_MASK) )
  2532.             {
  2533.                 /* If we are auto-getting TGTs, try */
  2534.                 if ( !ck_krb5_is_tgt_valid() ) {
  2535.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2536.                 }
  2537.                 krb5_msg = 1;
  2538.             }
  2539.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2540.                       AUTH_CLIENT_TO_SERVER &&
  2541.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2542.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2543.                      AUTH_ENCRYPT_USING_TELOPT) &&
  2544.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2545.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2546.                     continue;
  2547.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2548.                      AUTH_ENCRYPT_START_TLS) &&
  2549.                      (!ck_ssleay_is_installed()
  2550. #ifdef CK_SSL
  2551.                        || !(tls_active_flag || ssl_active_flag)
  2552. #endif /* CK_SSL */
  2553.                        ))
  2554.                     continue;
  2555.  
  2556.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2557. #ifdef CK_ENCRYPTION
  2558.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2559.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2560.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2561.                 }
  2562. #endif /* CK_ENCRYPTION */
  2563. #ifdef CK_SSL
  2564.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2565.                      ck_ssleay_is_installed() &&
  2566.                      (tls_active_flag || ssl_active_flag) ) {
  2567.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2568.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2569.                 }
  2570. #endif /* CK_SSL */
  2571.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2572.                 authentication_version = AUTHTYPE_KERBEROS_V5;
  2573.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2574.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2575.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2576.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2577.                 }
  2578.                 break;
  2579.             }
  2580.         }
  2581. #endif /* KRB5 */
  2582. #ifdef KRB4
  2583.         if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2584. #ifdef OS2
  2585.              hKRB4_32 &&
  2586. #endif /* OS2 */
  2587. #ifdef NO_FTP_AUTH
  2588.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2589. #endif /* NO_FTP_AUTH */
  2590.              ck_krb4_is_installed() && !krb4_msg) {
  2591.             int rc = 0;
  2592.  
  2593.             /* Without encryption we can't perform mutual authentication */
  2594.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2595.                  !ck_crypt_is_installed() )
  2596.                 continue;
  2597.  
  2598.             if ( !k4_auth_send() )
  2599.             {
  2600.                 /* If we are auto-getting TGTs, try */
  2601.                 if ( !ck_krb4_is_tgt_valid() ) {
  2602.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2603.                 }
  2604.                 krb4_msg = 1;
  2605.             }
  2606.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2607.                       AUTH_CLIENT_TO_SERVER &&
  2608.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2609. #ifdef CK_ENCRYPTION
  2610.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2611.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2612.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2613.                     continue;
  2614.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2615.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2616.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2617.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2618.                 }
  2619. #endif /* CK_ENCRYPTION */
  2620.                 authentication_version = AUTHTYPE_KERBEROS_V4;
  2621.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2622.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2623.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2624.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2625.                 }
  2626.                 break;
  2627.             }
  2628.         }
  2629. #endif /* KRB4 */
  2630.     }
  2631.     } else {
  2632.         for (i = 2; i+1 <= end_sub; i += 2) {
  2633. #ifdef CK_SSL
  2634.             if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
  2635. #ifdef SSLDLL
  2636.                  ck_ssleay_is_installed() &&
  2637. #endif /* SSLDLL */
  2638.                  !tls_active_flag && !ssl_active_flag && ssl_initialized
  2639. #ifndef USE_CERT_CB
  2640.                  && tls_load_certs(ssl_ctx,ssl_con,0)
  2641. #endif /* USE_CERT_CB */
  2642.                  )
  2643.             {
  2644.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2645.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2646. #ifdef CK_ENCRYPTION
  2647.                     /* SSL does not support Telnet Encryption */
  2648.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2649.                         continue;
  2650.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2651. #endif /* CK_ENCRYPTION */
  2652.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2653.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2654.                     authentication_version = AUTHTYPE_SSL;
  2655.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2656.                     break;
  2657.                 }
  2658.             }
  2659. #endif /* SSL */
  2660. #ifdef CK_SRP
  2661.             if ( atok(AUTHTYPE_SRP) &&
  2662.                  parsedat[i] == AUTHTYPE_SRP
  2663. #ifdef SRPDLL
  2664.                  && hSRP
  2665. #endif /* SRPDLL */
  2666. #ifdef NO_FTP_AUTH
  2667.                  && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2668. #endif /* NO_FTP_AUTH */
  2669.                  ) {
  2670.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2671.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2672. #ifdef PRE_SRP_1_4_5
  2673.                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2674.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2675.                     continue;
  2676. #endif /* PRE_SRP_1_4_5 */
  2677.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2678.                      AUTH_ENCRYPT_USING_TELOPT) &&
  2679.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2680.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2681.                     continue;
  2682.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2683.                      AUTH_ENCRYPT_START_TLS) &&
  2684.                      (!ck_ssleay_is_installed()
  2685. #ifdef CK_SSL
  2686.                        || !(tls_active_flag || ssl_active_flag)
  2687. #endif /* CK_SSL */
  2688.                        ))
  2689.                     continue;
  2690.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2691. #ifdef CK_ENCRYPTION
  2692.                     if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2693.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2694.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2695.                     }
  2696. #endif /* CK_ENCRYPTION */
  2697. #ifdef CK_SSL
  2698.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2699.                      ck_ssleay_is_installed() &&
  2700.                      (tls_active_flag || ssl_active_flag) ) {
  2701.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2702.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2703.                 }
  2704. #endif /* CK_SSL */
  2705.                     authentication_version = AUTHTYPE_SRP;
  2706.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2707.                     break;
  2708.                 }
  2709.             }
  2710. #endif /* SRP */
  2711. #ifdef GSSAPI_KRB5
  2712.         if (atok(AUTHTYPE_GSSAPI_KRB5) &&
  2713.             parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
  2714.             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2715.             AUTH_ENCRYPT_AFTER_EXCHANGE &&
  2716. #ifdef OS2
  2717.             hGSSAPI &&
  2718. #endif /* OS2 */
  2719. #ifdef NO_FTP_AUTH
  2720.             strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2721. #endif /* NO_FTP_AUTH */
  2722.             ck_gssapi_is_installed() && !gssk5_msg)
  2723.         {
  2724.             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2725.                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2726.                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
  2727.             {
  2728.                 /* If we are auto-getting TGTs, try */
  2729.                 if ( !ck_krb5_is_tgt_valid() ) {
  2730.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2731.                 }
  2732.                 gssk5_msg = 1;
  2733.             }
  2734.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2735.                       AUTH_CLIENT_TO_SERVER &&
  2736.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2737.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2738. #ifdef CK_ENCRYPTION
  2739.                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
  2740.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2741.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2742.                 }
  2743. #endif /* CK_ENCRYPTION */
  2744.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2745.                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
  2746.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2747.                 break;
  2748.             }
  2749.         }
  2750. #endif /* GSSAPI_KRB5 */
  2751. #ifdef KRB5
  2752.             if ( atok(AUTHTYPE_KERBEROS_V5) &&
  2753.                  parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2754. #ifdef OS2
  2755.                  hKRB5_32 &&
  2756. #endif /* OS2 */
  2757. #ifdef NO_FTP_AUTH
  2758.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2759. #endif /* NO_FTP_AUTH */
  2760.                  ck_krb5_is_installed() && !krb5_msg) {
  2761.  
  2762.                 /* Without encryption we can't perform mutual authentication */
  2763.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2764.                      !ck_crypt_is_installed())
  2765.                     continue;
  2766.  
  2767.                 /* Skip over entries that request credential forwarding */
  2768.                 /* if we are not forwarding.                            */
  2769.                 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2770.                      (forward_flag &&
  2771.                        ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2772.                     continue;
  2773.  
  2774.                 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2775.                                     parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2776.                                     parsedat[i+1] & INI_CRED_FWD_MASK) )
  2777.                 {
  2778.                     /* If we are auto-getting TGTs, try */
  2779.                     if ( !ck_krb5_is_tgt_valid() ) {
  2780.                         printf(
  2781.                            "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2782.                     }
  2783.                     krb5_msg = 1;
  2784.                 }
  2785.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2786.                           AUTH_CLIENT_TO_SERVER &&
  2787.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2788.                 {
  2789.                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2790.                          AUTH_ENCRYPT_USING_TELOPT) &&
  2791.                          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2792.                            TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2793.                         continue;
  2794.                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2795.                          AUTH_ENCRYPT_START_TLS) &&
  2796.                          (!ck_ssleay_is_installed()
  2797. #ifdef CK_SSL
  2798.                            || !(tls_active_flag || ssl_active_flag)
  2799. #endif /* CK_SSL */
  2800.                            ))
  2801.                         continue;
  2802.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2803. #ifdef CK_ENCRYPTION
  2804.                     if (auth_crypt) {
  2805.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2806.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2807.                     }
  2808. #endif /* CK_ENCRYPTION */
  2809. #ifdef CK_SSL
  2810.                     if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2811.                          ck_ssleay_is_installed() &&
  2812.                          (tls_active_flag || ssl_active_flag) ) {
  2813.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2814.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2815.                     }
  2816. #endif /* CK_SSL */
  2817.                     authentication_version = AUTHTYPE_KERBEROS_V5;
  2818.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2819.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2820.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2821.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2822.                     }
  2823.                     break;
  2824.                 }
  2825.             }
  2826. #endif /* KRB5 */
  2827. #ifdef KRB4
  2828.             if ( atok(AUTHTYPE_KERBEROS_V4) &&
  2829.                  parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2830. #ifdef OS2
  2831.                  hKRB4_32 &&
  2832. #endif /* OS2 */
  2833. #ifdef NO_FTP_AUTH
  2834.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2835. #endif /* NO_FTP_AUTH */
  2836.                  ck_krb4_is_installed() && !krb4_msg) {
  2837.                 int rc = 0;
  2838.  
  2839.                 /* Without encryption we can't perform mutual authentication */
  2840.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2841.                      !ck_crypt_is_installed())
  2842.                     continue;
  2843.  
  2844.                 if ( !k4_auth_send() )
  2845.                 {
  2846.                     /* If we are auto-getting TGTs, try */
  2847.                     if ( !ck_krb4_is_tgt_valid() ) {
  2848.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2849.                     }
  2850.                     krb4_msg = 1;
  2851.                 }
  2852.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2853.                           AUTH_CLIENT_TO_SERVER &&
  2854.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2855.                 {
  2856. #ifdef CK_ENCRYPTION
  2857.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2858.                         (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2859.                          TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2860.                       continue;
  2861.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2862.                     if (auth_crypt) {
  2863.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2864.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2865.                     }
  2866. #endif /* CK_ENCRYPTION */
  2867.                     authentication_version = AUTHTYPE_KERBEROS_V4;
  2868.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2869.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2870.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2871.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2872.                     }
  2873.                     break;
  2874.                 }
  2875.             }
  2876. #endif /* KRB4 */
  2877. #ifdef NTLM
  2878.         if ( atok(AUTHTYPE_NTLM) &&
  2879.              parsedat[i] == AUTHTYPE_NTLM &&
  2880.              ck_ntlm_is_valid(1) &&
  2881.              ntlm_auth_send() == 0) {
  2882.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2883.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2884. #ifdef CK_ENCRYPTION
  2885.                 /* NTLM does not support Telnet Encryption */
  2886.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2887.                     continue;
  2888.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2889. #endif /* CK_ENCRYPTION */
  2890.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2891.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2892.                 authentication_version = AUTHTYPE_NTLM;
  2893.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2894.                 break;
  2895.             }
  2896.         }
  2897. #endif /* NTLM */
  2898.         }
  2899.     }
  2900.  
  2901.     if (auth_how == -1) {               /* Did we find one? */
  2902.         switch ( auth_type_user[0] ) {  /* If not, abort the negotiation */
  2903.         case AUTHTYPE_NULL:
  2904.             auth_abort("User refused to accept any authentication method",0);
  2905.             break;
  2906.         case AUTHTYPE_AUTO:
  2907.             auth_abort("No authentication method available", 0);
  2908.             break;
  2909.         default: {
  2910.             char msg[80];
  2911.             ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]),
  2912.                       " could not be negotiated",NULL,NULL
  2913.                      );
  2914.             auth_abort(msg, 0);
  2915.         }
  2916.         }
  2917.         auth_finished(AUTH_REJECT);
  2918.         return AUTH_FAILURE;
  2919.     }
  2920.  
  2921.     printf("Authenticating with %s\r\n",
  2922.             AUTHTYPE_NAME(authentication_version));
  2923.  
  2924.     /* Send Telnet Auth Name message (if necessary) */
  2925.     switch ( authentication_version ) {
  2926.     case AUTHTYPE_SRP:
  2927.     case AUTHTYPE_KERBEROS_V4:
  2928.     case AUTHTYPE_KERBEROS_V5:
  2929.     case AUTHTYPE_GSSAPI_KRB5:
  2930.         /* if we do not have a name to login with get one now. */
  2931.         while ( szUserName[0] == '\0' ) {
  2932.             extern char * tn_pr_uid;
  2933.             int ok = uq_txt(NULL,
  2934.                      tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
  2935.                             1, NULL, szUserName, 63, NULL,DEFAULT_UQ_TIMEOUT);
  2936.             if ( !ok )
  2937.                 return AUTH_FAILURE;
  2938.         }
  2939.         plen = strlen(szUserName);
  2940.         pname = (unsigned char *) szUserName;
  2941.  
  2942.         /* Construct Telnet Debugging Message */
  2943.         if (deblog || tn_deb || debses) {
  2944.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  2945.                        "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2946.                        " NAME ",(char *)pname," IAC SE",NULL,
  2947.                        NULL,NULL,NULL,NULL,NULL,NULL
  2948.                      );
  2949.             debug(F100,tn_msg,"",0);
  2950.             if (tn_deb || debses) tn_debug(tn_msg);
  2951.         }
  2952.  
  2953.         /* Construct and send Authentication Name subnegotiation */
  2954.         if ( plen < sizeof(buf) - 6 ) {
  2955.             sprintf((char *)buf, "%c%c%c%c", IAC, SB, 
  2956.                      TELOPT_AUTHENTICATION,
  2957.                      TELQUAL_NAME);
  2958.             memcpy(&buf[4], pname, plen);               /* safe */
  2959.             sprintf((char *)&buf[plen + 4], "%c%c", IAC, SE);   /* safe */
  2960. #ifdef OS2
  2961.             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2962. #endif
  2963.             ttol((CHAR *)buf, plen+6);
  2964. #ifdef OS2
  2965.             ReleaseTelnetMutex();
  2966. #endif
  2967.         } else {
  2968.             sprintf((char *)buf, "%c%c%c%c%c%c", IAC, SB, 
  2969.                      TELOPT_AUTHENTICATION,
  2970.                      TELQUAL_NAME, IAC, SE);    /* safe */
  2971. #ifdef OS2
  2972.             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2973. #endif
  2974.             ttol((CHAR *)buf, 6);
  2975. #ifdef OS2
  2976.             ReleaseTelnetMutex();
  2977. #endif
  2978.         }
  2979.     }
  2980.  
  2981.     /* Construct Authentication Mode subnegotiation message (if necessary) */
  2982.     switch ( authentication_version ) {
  2983.     case AUTHTYPE_SRP:
  2984.     case AUTHTYPE_KERBEROS_V4:
  2985.     case AUTHTYPE_KERBEROS_V5:
  2986.     case AUTHTYPE_GSSAPI_KRB5:
  2987.     case AUTHTYPE_NTLM:
  2988.         mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt
  2989. #ifdef USE_INI_CRED_FWD
  2990.                | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
  2991.                   auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  2992. #endif /* USE_INI_CRED_FWD */
  2993.                ;
  2994.         sprintf((char *)buf, "%c%c%c%c%c%c%c",
  2995.                  IAC, SB, TELOPT_AUTHENTICATION,
  2996.                  TELQUAL_IS,
  2997.                  authentication_version,
  2998.                  mode,
  2999.                  KRB_AUTH);     /* safe */
  3000.         break;
  3001.     }
  3002.  
  3003.     /* Send initial authentication data */
  3004.     switch ( authentication_version ) {
  3005. #ifdef CK_SSL
  3006.     case AUTHTYPE_SSL:
  3007.         SendSSLAuthSB(SSL_START,NULL,0);
  3008.         break;
  3009. #endif /* SSL */
  3010. #ifdef CK_SRP
  3011.     case AUTHTYPE_SRP:
  3012.         sprintf(&buf[7], "%c%c", IAC, SE);      /* safe */
  3013.         if (deblog || tn_deb || debses) {
  3014.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3015.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  3016.                       " IS ",AUTHTYPE_NAME(authentication_version),
  3017.                       " AUTH ",AUTHMODE_NAME(mode)," IAC SE",
  3018.                       NULL,NULL,NULL,NULL,NULL
  3019.                      );
  3020.             debug(F100,tn_msg,"",0);
  3021.             if (tn_deb || debses) tn_debug(tn_msg);
  3022.         }
  3023. #ifdef OS2
  3024.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3025. #endif
  3026.         ttol((CHAR *)buf, 9);
  3027. #ifdef OS2
  3028.         ReleaseTelnetMutex();
  3029. #endif
  3030.         break;
  3031. #endif /* SRP */
  3032. #ifdef NTLM
  3033.     case AUTHTYPE_NTLM: {
  3034.         int length = 0;
  3035.  
  3036.         for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) {
  3037.             if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC )
  3038.                 iaccnt++;
  3039.         }
  3040.  
  3041.         if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10)  <
  3042.              sizeof(buf) ) {
  3043.             length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],
  3044.                                    2*sizeof(ULONG));
  3045.             length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
  3046.                                   NTLMSecBuf[0].cbBuffer);
  3047.         }
  3048.         sprintf(&buf[7+length], "%c%c", IAC, SE);
  3049.  
  3050.         if (deblog || tn_deb || debses) {
  3051.             int i;
  3052.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3053.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  3054.                       " IS ",AUTHTYPE_NAME(authentication_version)," ",
  3055.                       AUTHMODE_NAME(mode)," NTLM_AUTH ",
  3056.                        NULL,NULL,NULL,NULL,NULL
  3057.                       );
  3058.             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],length);
  3059.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3060.             debug(F100,tn_msg,"",0);
  3061.             if (tn_deb || debses) tn_debug(tn_msg);
  3062.         }
  3063. #ifdef OS2
  3064.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3065. #endif
  3066.         ttol((CHAR *)buf, length+9);
  3067. #ifdef OS2
  3068.         ReleaseTelnetMutex();
  3069. #endif
  3070.         break;
  3071.     }
  3072. #endif /* NTLM */
  3073. #ifdef KRB4
  3074.     case AUTHTYPE_KERBEROS_V4:
  3075.         for ( i=0 ; i<k4_auth.length ; i++ ) {
  3076.             if ( k4_auth.dat[i] == IAC )
  3077.                 iaccnt++;
  3078.         }
  3079.  
  3080.         if ( k4_auth.length + iaccnt + 10 < sizeof(buf) )
  3081.           k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
  3082.         else
  3083.             k4_auth.length = 0;
  3084.         sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
  3085.  
  3086.         if (deblog || tn_deb || debses) {
  3087.             int i;
  3088.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3089.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3090.                       AUTHTYPE_NAME(authentication_version)," ",
  3091.                       AUTHMODE_NAME(mode)," AUTH ",
  3092.                       NULL,NULL,NULL,NULL,NULL
  3093.                      );
  3094.             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length);
  3095.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3096.             debug(F100,tn_msg,"",0);
  3097.             if (tn_deb || debses) tn_debug(tn_msg);
  3098.         }
  3099. #ifdef OS2
  3100.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3101. #endif
  3102.         ttol((CHAR *)buf, k4_auth.length+9);
  3103. #ifdef OS2
  3104.         ReleaseTelnetMutex();
  3105. #endif
  3106.  
  3107. #ifndef REMOVE_FOR_EXPORT
  3108. #ifdef CK_ENCRYPTION
  3109.         /*
  3110.          * If we are doing mutual authentication, get set up to send
  3111.          * the challenge, and verify it when the response comes back.
  3112.          */
  3113.         if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  3114.             register int i;
  3115.             int rc = 0;
  3116.  
  3117. #ifdef MIT_CURRENT
  3118.             data.data = cred.session;
  3119.             data.length = 8; /* sizeof(cred.session) */;
  3120.  
  3121.             if (code = krb5_c_random_seed(k5_context, &data)) {
  3122.                 com_err("libtelnet", code,
  3123.                          "while seeding random number generator");
  3124.                 return(0);
  3125.             }
  3126.  
  3127.             if (code = krb5_c_make_random_key(k5_context,
  3128.                                                ENCTYPE_DES_CBC_RAW,
  3129.                                                &random_key)) {
  3130.                 com_err("libtelnet", code,
  3131.                          "while creating random session key");
  3132.                 return(0);
  3133.             }
  3134.  
  3135.             /* the krb4 code uses ecb mode, but on a single block
  3136.             with a zero ivec, ecb and cbc are the same */
  3137.             k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  3138.             k4_krbkey.length = 8;
  3139.             k4_krbkey.contents = cred.session;
  3140.  
  3141.             encdata.ciphertext.data = random_key.contents;
  3142.             encdata.ciphertext.length = random_key.length;
  3143.             encdata.enctype = ENCTYPE_UNKNOWN;
  3144.  
  3145.             data.data = k4_session_key;
  3146.             data.length = 8;
  3147.  
  3148.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3149.                                    &encdata, &data);
  3150.  
  3151.             krb5_free_keyblock_contents(k5_context, &random_key);
  3152.  
  3153.             if (code) {
  3154.                 com_err("libtelnet", code, "while encrypting random key");
  3155.                 return(0);
  3156.             }
  3157.  
  3158.             encdata.ciphertext.data = k4_session_key;
  3159.             encdata.ciphertext.length = 8;
  3160.             encdata.enctype = ENCTYPE_UNKNOWN;
  3161.  
  3162.             data.data = k4_challenge;
  3163.             data.length = 8;
  3164.  
  3165.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3166.                                    &encdata, &data);
  3167. #else /* MIT_CURRENT */
  3168.             memset(k4_sched,0,sizeof(Schedule));
  3169.             ckhexdump("auth_send",cred.session,8);
  3170.             rc = des_key_sched(cred.session, k4_sched);
  3171.             if ( rc == -1 ) {
  3172.                 printf("?Invalid DES key specified in credentials\r\n");
  3173.                 debug(F110,"auth_send",
  3174.                       "invalid DES Key specified in credentials",0);
  3175.             } else if ( rc == -2 ) {
  3176.                 printf("?Weak DES key specified in credentials\r\n");
  3177.                 debug(F110,"auth_send",
  3178.                       "weak DES Key specified in credentials",0);
  3179.             } else if ( rc != 0 ) {
  3180.                 printf("?DES Key Schedule not set by credentials\r\n");
  3181.                 debug(F110,"auth_send",
  3182.                       "DES Key Schedule not set by credentials",0);
  3183.             }
  3184.             ckhexdump("auth_send schedule",k4_sched,8*16);
  3185.  
  3186.             des_set_random_generator_seed(cred.session);
  3187.  
  3188.             do {
  3189.                 des_new_random_key(k4_session_key);
  3190.                 des_fixup_key_parity(k4_session_key);
  3191.             } while ( ck_des_is_weak_key(k4_session_key) );
  3192.  
  3193.             ckhexdump("auth_send des_new_random_key(k4_session_key)",
  3194.                      k4_session_key,8);
  3195.  
  3196.             /* Decrypt the session key so that we can send it to the */
  3197.             /* host as a challenge                                   */
  3198. #ifdef NT
  3199.             des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
  3200. #else /* NT */
  3201.             des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
  3202. #endif /* NT */
  3203.             ckhexdump(
  3204.                 "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
  3205.                 k4_session_key,8
  3206.                     );
  3207.             /* Prepare the result of the challenge */
  3208.             /* Decrypt the session_key, add 1, and then encrypt it */
  3209.             /* The result stored in k4_challenge should match the  */
  3210.             /* KRB4_RESPONSE value from the host.                  */
  3211. #ifdef NT
  3212.             des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
  3213. #else /* NT */
  3214.             des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
  3215. #endif /* NT */
  3216.  
  3217.             ckhexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
  3218.                      k4_challenge,8);
  3219. #endif /* MIT_CURRENT */
  3220.             /*
  3221.             * Increment the challenge by 1, and encrypt it for
  3222.             * later comparison.
  3223.             */
  3224.             for (i = 7; i >= 0; --i) {
  3225.                 register int x;
  3226.                 x = (unsigned int)k4_challenge[i] + 1;
  3227.                 k4_challenge[i] = x;    /* ignore overflow */
  3228.                 if (x < 256)            /* if no overflow, all done */
  3229.                     break;
  3230.             }
  3231.             ckhexdump("auth_send k4_challenge+1",k4_challenge,8);
  3232. #ifdef MIT_CURRENT
  3233.             data.data = k4_challenge;
  3234.             data.length = 8;
  3235.  
  3236.             encdata.ciphertext.data = k4_challenge;
  3237.             encdata.ciphertext.length = 8;
  3238.             encdata.enctype = ENCTYPE_UNKNOWN;
  3239.  
  3240.             if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
  3241.                                        &encdata)) {
  3242.                 com_err("libtelnet", code, "while encrypting random key");
  3243.                 return(0);
  3244.             }
  3245. #else /* MIT_CURRENT */
  3246. #ifdef NT
  3247.             des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  3248. #else /* NT */
  3249.             des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  3250. #endif /* NT */
  3251.             ckhexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
  3252.                      k4_challenge,8);
  3253. #endif /* MIT_CURRENT */
  3254.         }
  3255. #endif  /* ENCRYPTION */
  3256. #endif /* REMOVE_FOR_EXPORT */
  3257.         break;
  3258. #endif /* KRB4 */
  3259. #ifdef GSSAPI_KRB5
  3260.     case AUTHTYPE_GSSAPI_KRB5:
  3261.         for ( i=0 ; i<gss_send_tok.length ; i++ ) {
  3262.             if ( ((char *)gss_send_tok.value)[i] == IAC )
  3263.                 iaccnt++;
  3264.         }
  3265.  
  3266.         if ( gss_send_tok.length + iaccnt + 10 < sizeof(buf) )
  3267.             gss_send_tok.length = copy_for_net(&buf[7], gss_send_tok.value,
  3268.                                                gss_send_tok.length);
  3269.         else
  3270.             gss_send_tok.length = 0;
  3271.         sprintf(&buf[gss_send_tok.length+7], "%c%c", IAC, SE);       /* safe */
  3272.         if (deblog || tn_deb || debses) {
  3273.             int i;
  3274.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3275.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3276.                       AUTHTYPE_NAME(authentication_version)," ",
  3277.                       AUTHMODE_NAME(mode)," AUTH ",
  3278.                       NULL,NULL,NULL,NULL,NULL
  3279.                      );
  3280.             tn_hex((char *)tn_msg,TN_MSG_LEN,&buf[7],gss_send_tok.length);
  3281.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3282.             debug(F100,tn_msg,"",0);
  3283.             if (tn_deb || debses) tn_debug(tn_msg);
  3284.         }
  3285. #ifdef OS2
  3286.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3287. #endif
  3288.         ttol((CHAR *)buf, gss_send_tok.length+9);
  3289. #ifdef OS2
  3290.         ReleaseTelnetMutex();
  3291. #endif
  3292.         break;
  3293. #endif /* GSSAPI_KRB5 */
  3294. #ifdef KRB5
  3295.     case AUTHTYPE_KERBEROS_V5:
  3296.         debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
  3297.         for ( i=0 ; i<k5_auth.length ; i++ ) {
  3298.             if ( (char *)k5_auth.data[i] == IAC )
  3299.                 iaccnt++;
  3300.         }
  3301.         if ( k5_auth.length + iaccnt + 10 < sizeof(buf) ) {
  3302.         k5_auth.length = copy_for_net(&buf[7],
  3303.                       (CHAR *)k5_auth.data,
  3304.                       k5_auth.length);
  3305.     } else {
  3306.           debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
  3307.           k5_auth.length = 0;
  3308.         }
  3309.  
  3310.         sprintf((char *)&buf[k5_auth.length+7], "%c%c", IAC, SE); /* safe */
  3311.         if (deblog || tn_deb || debses) {
  3312.             int i;
  3313.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3314.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3315.                       AUTHTYPE_NAME(authentication_version)," ",
  3316.                       AUTHMODE_NAME(mode)," AUTH ",
  3317.                       NULL,NULL,NULL,NULL,NULL
  3318.                      );
  3319.             tn_hex((CHAR *)tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
  3320.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3321.             debug(F100,tn_msg,"",0);
  3322.             if (tn_deb || debses) tn_debug(tn_msg);
  3323.         }
  3324. #ifdef OS2
  3325.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3326. #endif
  3327.         ttol((CHAR *)buf, k5_auth.length+9);
  3328. #ifdef OS2
  3329.         ReleaseTelnetMutex();
  3330. #endif
  3331. #ifdef HEIMDAL
  3332.         krb5_data_free(&k5_auth);
  3333. #else /* HEIMDAL */
  3334.         krb5_free_data_contents(k5_context,&k5_auth);
  3335.         memset(&k5_auth,0,sizeof(krb5_data));
  3336. #endif /* HEIMDAL */
  3337.         break;
  3338. #endif /* KRB5 */
  3339.     }
  3340.     return AUTH_SUCCESS;
  3341. }
  3342.  
  3343. /*
  3344.  * Function: Parse authentication REPLY command
  3345.  *
  3346.  * Parameters:
  3347.  *  parsedat - the sub-command data.
  3348.  *
  3349.  *      end_sub - index of the character in the 'parsedat' array which
  3350.  *              is the last byte in a sub-negotiation
  3351.  *
  3352.  * Returns: Kerberos error code.
  3353.  */
  3354. static int
  3355. #ifdef CK_ANSIC
  3356. auth_reply(unsigned char *parsedat, int end_sub)
  3357. #else
  3358. auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3359. #endif
  3360. {
  3361.     int n = AUTH_FAILURE;
  3362.  
  3363.     if ( parsedat[2] != authentication_version ) {
  3364.         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
  3365.                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
  3366.                 AUTHTYPE_NAME(authentication_version),authentication_version);
  3367.         auth_finished(AUTH_REJECT);
  3368.         return(AUTH_FAILURE);
  3369.     }
  3370.     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
  3371.         printf("Authentication mode mismatch (%s != %s)\r\n",
  3372.                 AUTHMODE_NAME(parsedat[3]),
  3373.                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
  3374.         auth_finished(AUTH_REJECT);
  3375.         return(AUTH_FAILURE);
  3376.     }
  3377.  
  3378. #ifdef KRB4
  3379.     if (authentication_version == AUTHTYPE_KERBEROS_V4)
  3380.         n = k4_auth_reply(parsedat, end_sub);
  3381. #endif
  3382. #ifdef KRB5
  3383.     if (authentication_version == AUTHTYPE_KERBEROS_V5)
  3384.         n = k5_auth_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3385. #endif
  3386. #ifdef CK_SRP
  3387.     if (authentication_version == AUTHTYPE_SRP) {
  3388. #ifndef PRE_SRP_1_7_3
  3389.         n = new_srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3390. #else /* PRE_SRP_1_7_3 */
  3391.         n = srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3392. #endif /* PRE_SRP_1_7_3 */
  3393.     }
  3394. #endif /* SRP */
  3395. #ifdef CK_SSL
  3396.     if (authentication_version == AUTHTYPE_SSL)
  3397.         n = ssl_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3398. #endif /* SSL */
  3399. #ifdef NTLM
  3400.     if (authentication_version == AUTHTYPE_NTLM)
  3401.         n = ntlm_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3402. #endif /* NTLM */
  3403.     return n;
  3404. }
  3405.  
  3406.  
  3407. /*
  3408.  * Function: Parse authentication IS command
  3409.  *
  3410.  * Parameters:
  3411.  *  parsedat - the sub-command data.
  3412.  *
  3413.  *      end_sub - index of the character in the 'parsedat' array which
  3414.  *              is the last byte in a sub-negotiation
  3415.  *
  3416.  * Returns: Kerberos error code.
  3417.  */
  3418. static int
  3419. #ifdef CK_ANSIC
  3420. auth_is(unsigned char *parsedat, int end_sub)
  3421. #else
  3422. auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3423. #endif
  3424. {
  3425.     int n = AUTH_FAILURE;
  3426.  
  3427.     if ( parsedat[2] == AUTHTYPE_NULL ) {
  3428.         auth_finished(AUTH_REJECT);
  3429.         return(AUTH_FAILURE);
  3430.     }
  3431.  
  3432.     /*
  3433.      *  If CLIENT_CHOOSE_ONCE is selected the server will not allow the
  3434.      *  client to switch to an alternate authentication method if the one
  3435.      *  it originally selected fails.  (ie, if the host's SRP parameters
  3436.      *  are invalid.)  However, I think this is a bit of a security risk
  3437.      *  since allowing that functionality means that it is impossible to
  3438.      *  detect if an attack is being carried out on
  3439.      */
  3440. #define CLIENT_CHOOSE_ONCE
  3441. #ifdef CLIENT_CHOOSE_ONCE
  3442.     if ( authentication_version == AUTHTYPE_AUTO )
  3443. #endif /* CLIENT_CHOOSE_ONCE */
  3444.     {
  3445.         /* this block of code needs to check the initial parameters */
  3446.         /* to ensure that those returned match one of the sets that */
  3447.         /* were sent to the client in the first place.              */
  3448.  
  3449.         int i=0;
  3450.         for ( i=4; str_request[i] != IAC ; i+=2) {
  3451.             if (str_request[i] == parsedat[2] &&
  3452.                  str_request[i+1] == parsedat[3])
  3453.                 break;
  3454.         }
  3455.  
  3456.         if ( str_request[i] == IAC ) {
  3457.             printf("Invalid authentication type pair (%s,%s)\r\n",
  3458.                     AUTHTYPE_NAME(parsedat[2]),
  3459.                     AUTHMODE_NAME(parsedat[3]));
  3460.             auth_finished(AUTH_REJECT);
  3461.             return(AUTH_FAILURE);
  3462.         }
  3463.  
  3464.         if (authentication_version != parsedat[2]) {
  3465.             authentication_version = parsedat[2];
  3466.             auth_how = (parsedat[3] & AUTH_HOW_MASK);
  3467.             auth_crypt = (parsedat[3] & AUTH_ENCRYPT_MASK);
  3468.             auth_fwd = (parsedat[3] & INI_CRED_FWD_MASK);
  3469.             debug(F111,"auth_is","authentication_version",
  3470.                   authentication_version);
  3471.             debug(F111,"auth_is","auth_how",auth_how);
  3472.             debug(F111,"auth_is","auth_crypt",auth_crypt);
  3473.             debug(F111,"auth_is","auth_fwd",auth_fwd);
  3474.         }
  3475.     }
  3476.  
  3477. #ifdef CLIENT_CHOOSE_ONCE
  3478.     if ( parsedat[2] != authentication_version ) {
  3479.         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
  3480.                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
  3481.                 AUTHTYPE_NAME(authentication_version),authentication_version);
  3482.         auth_finished(AUTH_REJECT);
  3483.         return(AUTH_FAILURE);
  3484.     }
  3485.     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
  3486.         printf("Authentication mode mismatch (%s != %s)\r\n",
  3487.                 AUTHMODE_NAME(parsedat[3]),
  3488.                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
  3489.         auth_finished(AUTH_REJECT);
  3490.         return(AUTH_FAILURE);
  3491.     }
  3492. #endif /* CLIENT_CHOOSE_ONCE */
  3493.  
  3494.     switch (authentication_version) {
  3495. #ifdef KRB4
  3496.     case AUTHTYPE_KERBEROS_V4:
  3497.         n = k4_auth_is(parsedat, end_sub);
  3498.         break;
  3499. #endif
  3500. #ifdef KRB5
  3501.     case AUTHTYPE_KERBEROS_V5:
  3502.         n = k5_auth_is(parsedat[3],parsedat, end_sub);
  3503.         break;
  3504. #endif
  3505. #ifdef CK_SRP
  3506.     case AUTHTYPE_SRP:
  3507. #ifndef PRE_SRP_1_7_3
  3508.         n = new_srp_is(parsedat[3], parsedat, end_sub);
  3509. #else /* PRE_SRP_1_7_3 */
  3510.         n = srp_is(parsedat[3], parsedat, end_sub);
  3511. #endif /* PRE_SRP_1_7_3 */
  3512.         break;
  3513. #endif /* SRP */
  3514. #ifdef CK_SSL
  3515.     case AUTHTYPE_SSL:
  3516.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3517.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3518.         n = ssl_is(parsedat, end_sub);
  3519.         break;
  3520. #endif /* SSL */
  3521. #ifdef NTLM
  3522.     case AUTHTYPE_NTLM:
  3523.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3524.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3525.         n = ntlm_is(parsedat, end_sub);
  3526.         break;
  3527. #endif /* NTLM */
  3528.     case AUTHTYPE_NULL:
  3529.     default:
  3530.         n = AUTH_FAILURE;
  3531.     }
  3532.     debug(F111,"auth_is","n",n);
  3533.     return n;
  3534. }
  3535.  
  3536. /*
  3537.  * Function: Parse authentication NAME command
  3538.  *
  3539.  * Parameters:
  3540.  *  parsedat - the sub-command data.
  3541.  *
  3542.  *      end_sub - index of the character in the 'parsedat' array which
  3543.  *              is the last byte in a sub-negotiation
  3544.  *
  3545.  * Returns: Kerberos error code.
  3546.  */
  3547. static int
  3548. #ifdef CK_ANSIC
  3549. auth_name(unsigned char *parsedat, int end_sub)
  3550. #else
  3551. auth_name(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3552. #endif
  3553. {
  3554.     int len = (end_sub-2) > 63 ? 63 : (end_sub-2);
  3555.     if ( len > 0 && (len + 1) < sizeof(szUserNameRequested)) {
  3556.         memcpy(szUserNameRequested,&parsedat[2],len);           /* safe */
  3557.         szUserNameRequested[len] = '\0';
  3558.     } else
  3559.       szUserNameRequested[0] = '\0';
  3560.     debug(F111,"auth_name szUserNameRequested",szUserNameRequested,len);
  3561.     return(AUTH_SUCCESS);
  3562. }
  3563.  
  3564. /*
  3565.  * Function: Parse the athorization sub-options and reply.
  3566.  *
  3567.  * Parameters:
  3568.  *      parsedat - sub-option string to parse.
  3569.  *
  3570.  *      end_sub - last charcter position in parsedat.
  3571.  */
  3572. int
  3573. auth_parse(unsigned char *parsedat, int end_sub)
  3574. {
  3575.     int rc = AUTH_FAILURE;
  3576.     switch (parsedat[1]) {
  3577.     case TELQUAL_SEND:
  3578.         rc = auth_send(parsedat, end_sub);
  3579.         break;
  3580.     case TELQUAL_REPLY:
  3581.         rc= auth_reply(parsedat, end_sub);
  3582.         break;
  3583.     case TELQUAL_IS:
  3584.         rc = auth_is(parsedat, end_sub);
  3585.         break;
  3586.     case TELQUAL_NAME:
  3587.         rc = auth_name(parsedat, end_sub);
  3588.         break;
  3589.     }
  3590.     debug(F111,"auth_parse","rc",rc);
  3591.     return(rc);
  3592. }
  3593.  
  3594.  
  3595. /*
  3596.  * Function: Initialization routine called kstream encryption system.
  3597.  *
  3598.  * Parameters:
  3599.  *  data - user data.
  3600.  */
  3601. int
  3602. #ifdef CK_ANSIC
  3603. auth_init(kstream ks)
  3604. #else
  3605. auth_init(ks) kstream_ptr ks;
  3606. #endif
  3607. {
  3608. #ifdef FORWARD
  3609.     forwarded_tickets = 0;  /* were tickets forwarded? */
  3610. #endif /* FORWARD */
  3611. #ifdef CK_ENCRYPTION
  3612.     encrypt_init(ks,cx_type);
  3613. #endif
  3614.     return 0;
  3615. }
  3616.  
  3617.  
  3618. /*
  3619.  * Function: Destroy routine called kstream encryption system.
  3620.  *
  3621.  * Parameters:
  3622.  *  data - user data.
  3623.  */
  3624. VOID
  3625. #ifdef CK_ANSIC
  3626. auth_destroy(void)
  3627. #else
  3628. auth_destroy()
  3629. #endif
  3630. {
  3631. }
  3632.  
  3633.  
  3634. /*
  3635.  * Function: Callback to encrypt a block of characters
  3636.  *
  3637.  * Parameters:
  3638.  *  out - return as pointer to converted buffer.
  3639.  *
  3640.  *  in - the buffer to convert
  3641.  *
  3642.  * Returns: number of characters converted.
  3643.  */
  3644. int
  3645. #ifdef CK_ANSIC
  3646. auth_encrypt(struct kstream_data_block *out,
  3647.              struct kstream_data_block *in)
  3648. #else
  3649. auth_encrypt(out,in)
  3650.     struct kstream_data_block *out; struct kstream_data_block *in;
  3651. #endif
  3652. {
  3653.     out->ptr = in->ptr;
  3654.  
  3655.     out->length = in->length;
  3656.  
  3657.     return(out->length);
  3658. }
  3659.  
  3660.  
  3661. /*
  3662.  * Function: Callback to decrypt a block of characters
  3663.  *
  3664.  * Parameters:
  3665.  *  out - return as pointer to converted buffer.
  3666.  *
  3667.  *  in - the buffer to convert
  3668.  *
  3669.  * Returns: number of characters converted.
  3670.  */
  3671. int
  3672. #ifdef CK_ANSIC
  3673. auth_decrypt(struct kstream_data_block *out,
  3674.              struct kstream_data_block *in)
  3675. #else
  3676. auth_decrypt(out,in)
  3677.     struct kstream_data_block *out; struct kstream_data_block *in;
  3678. #endif
  3679. {
  3680.     out->ptr = in->ptr;
  3681.  
  3682.     out->length = in->length;
  3683.  
  3684.     return(out->length);
  3685. }
  3686.  
  3687. #ifdef KRB4
  3688. #ifdef NT
  3689. void
  3690. ck_krb4_debug(int x)
  3691. {
  3692.     set_krb_debug(x);
  3693.     set_krb_ap_req_debug(x);
  3694. }
  3695. #endif /* NT */
  3696. int
  3697. ck_krb4_autoget_TGT(char * realm)
  3698. {
  3699.     extern struct krb_op_data krb_op;
  3700.     extern struct krb4_init_data krb4_init;
  3701.     char passwd[PWD_SZ];
  3702.     char prompt[256];
  3703.     char * saverealm=NULL;
  3704.     int  rc = -1;
  3705.     extern char * k4prprompt;
  3706.     extern char * k4pwprompt;
  3707.  
  3708.     ini_kerb();         /* Place defaults in above structs */
  3709.     passwd[0] = '\0';
  3710.  
  3711.     if ( krb4_init.principal == NULL ||
  3712.          krb4_init.principal[0] == '\0') {
  3713.         int ok = uq_txt(NULL, 
  3714.                  k4prprompt && k4prprompt[0] ?
  3715.                  k4prprompt :
  3716.                  "Kerberos 4 Principal: ",
  3717.                  2, NULL, passwd,PWD_SZ-1, NULL, DEFAULT_UQ_TIMEOUT);
  3718.         if ( ok && passwd[0] )
  3719.             makestr(&krb4_init.principal,passwd);
  3720.         else
  3721.             return(0);
  3722.     }
  3723.  
  3724.     /* Save realm in init structure so it can be restored */
  3725.     if ( realm ) {
  3726.         saverealm = krb4_init.realm;
  3727.         krb4_init.realm = realm;
  3728.     }
  3729.  
  3730.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  3731.         int ok;
  3732.         if ( k4pwprompt && k4pwprompt[0] &&
  3733.              (strlen(k4pwprompt) + strlen(krb4_init.principal) +
  3734.                strlen(krb4_init.realm) - 4) < sizeof(prompt)) {
  3735.             sprintf(prompt,k4pwprompt,krb4_init.principal,krb4_init.realm);
  3736.         } else
  3737.             ckmakxmsg(prompt,sizeof(prompt),
  3738.                   "Kerberos 4 Password for ",krb4_init.principal,"@",
  3739.                   krb4_init.realm,": ",
  3740.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  3741.         ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
  3742.             DEFAULT_UQ_TIMEOUT);
  3743.         if ( !ok )
  3744.             passwd[0] = '\0';
  3745.     } else {
  3746.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  3747. #ifdef OS2
  3748.         if ( pwcrypt )
  3749.             ck_encrypt((char *)passwd);
  3750. #endif /* OS2 */
  3751.     }
  3752.  
  3753.     if ( passwd[0] ) {
  3754.         makestr(&krb4_init.password,passwd);
  3755.         rc = ck_krb4_initTGT(&krb_op, &krb4_init);
  3756.         free(krb4_init.password);
  3757.         krb4_init.password = NULL;
  3758.     }
  3759.  
  3760.     krb4_init.password = NULL;
  3761.     memset(passwd,0,PWD_SZ);
  3762.  
  3763.     /* restore realm to init structure if needed */
  3764.     if ( saverealm )
  3765.         krb4_init.realm = saverealm;
  3766.     return(rc == 0);
  3767. }
  3768.  
  3769. char *
  3770. ck_krb4_realmofhost(char *host)
  3771. {
  3772.     return (char *)krb_realmofhost(host);
  3773. }
  3774.  
  3775. /*
  3776.  *
  3777.  * K4_auth_send - gets authentication bits we need to send to KDC.
  3778.  *
  3779.  * Result is left in auth
  3780.  *
  3781.  * Returns: 0 on failure, 1 on success
  3782.  */
  3783. static int
  3784. #ifdef CK_ANSIC
  3785. k4_auth_send(void)
  3786. #else
  3787. k4_auth_send()
  3788. #endif
  3789. {
  3790.     int r=0;                                    /* Return value */
  3791.     char instance[INST_SZ+1]="";
  3792.     char *realm=NULL;
  3793.     char tgt[4*REALM_SZ+1];
  3794.  
  3795.     memset(instance, 0, sizeof(instance));
  3796.  
  3797. #ifdef COMMENT
  3798.     /* we only need to call krb_get_phost if the hostname */
  3799.     /* is not fully qualified.  But we have already done  */
  3800.     /* this in netopen() call.  This will save a round of */
  3801.     /* DNS queries.                                       */
  3802.     debug(F110,"k4_auth_send","krb_get_phost",0);
  3803.     if (realm = (char *)krb_get_phost(szHostName)) {
  3804.         ckstrncpy(instance, realm, INST_SZ);
  3805.     }
  3806. #else /* COMMENT */
  3807.     {
  3808.         char *p;
  3809.         ckstrncpy(instance, szHostName, INST_SZ);
  3810.         for ( p=instance; *p && *p != '.' ; p++ );
  3811.         *p = '\0';
  3812.     }
  3813. #endif /* COMMENT */
  3814.  
  3815.     debug(F110,"k4_auth_send","krb_get_realmofhost",0);
  3816.     realm = (char *)krb_realmofhost(szHostName);
  3817.  
  3818.     if (!realm) {
  3819.         strcpy(strTmp, "Can't find realm for host \"");
  3820.         ckstrncat(strTmp, szHostName,AUTHTMPBL);
  3821.         ckstrncat(strTmp, "\"",AUTHTMPBL);
  3822.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3823.         krb4_errno = r;
  3824.         makestr(&krb4_errmsg,strTmp);
  3825.         return(0);
  3826.     }
  3827.  
  3828.     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
  3829.     r = ck_krb4_tkt_isvalid(tgt);
  3830.  
  3831.     if ( r <= 0 && krb4_autoget )
  3832.         ck_krb4_autoget_TGT(realm);
  3833.  
  3834.     debug(F110,"k4_auth_send","krb_mk_req",0);
  3835.     r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3836.                     instance, realm, 0);
  3837.  
  3838.     if (r == 0) {
  3839.         debug(F110,"k4_auth_send","krb_get_cred",0);
  3840.         r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3841.                           instance, realm, &cred);
  3842.         if (r)
  3843.             debug(F111,"k4_auth_send","krb_get_cred() failed",r);
  3844.     }
  3845.     else
  3846.         debug(F111,"k4_auth_send","krb_mk_req() failed",r);
  3847.  
  3848.     if (r) {
  3849.         strcpy(strTmp, "Can't get \"");
  3850.         ckstrncat(strTmp,
  3851.                   krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,AUTHTMPBL);
  3852.         if (instance[0] != 0) {
  3853.             ckstrncat(strTmp, ".",AUTHTMPBL);
  3854.             ckstrncat(strTmp, instance,AUTHTMPBL);
  3855.         }
  3856.         ckstrncat(strTmp, "@",AUTHTMPBL);
  3857.         ckstrncat(strTmp, realm,AUTHTMPBL);
  3858.         ckstrncat(strTmp, "\" ticket\r\n  ",AUTHTMPBL);
  3859.         ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),AUTHTMPBL);
  3860.         debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
  3861.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3862.         krb4_errno = r;
  3863.         makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3864.         return(0);
  3865.     }
  3866.  
  3867. #ifdef OS2
  3868.     if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
  3869.         ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
  3870.     }
  3871. #endif /* OS2 */
  3872.     krb4_errno = r;
  3873.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3874.     debug(F110,"k4_auth_send",krb4_errmsg,0);
  3875.     return(1);
  3876. }
  3877.  
  3878. /*
  3879.  * Function: K4 parse authentication reply command
  3880.  *
  3881.  * Parameters:
  3882.  *  parsedat - the sub-command data.
  3883.  *
  3884.  *  end_sub - index of the character in the 'parsedat' array which
  3885.  *              is the last byte in a sub-negotiation
  3886.  *
  3887.  * Returns: Kerberos error code.
  3888.  */
  3889. static int
  3890. #ifdef CK_ANSIC
  3891. k4_auth_reply(unsigned char *parsedat, int end_sub)
  3892. #else
  3893. k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3894. #endif
  3895. {
  3896. #ifdef CK_ENCRYPTION
  3897.     Session_Key skey;
  3898. #ifdef MIT_CURRENT
  3899.     krb5_data kdata;
  3900.     krb5_enc_data encdata;
  3901.     krb5_error_code code;
  3902. #endif /* MIT_CURRENT */
  3903. #endif
  3904.     time_t t;
  3905.     int x;
  3906.     int i;
  3907.  
  3908.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  3909.         auth_finished(AUTH_REJECT);
  3910.         return AUTH_FAILURE;
  3911.     }
  3912.  
  3913.     if (parsedat[4] == KRB_REJECT) {
  3914.         strTmp[0] = 0;
  3915.  
  3916.         for (i = 5; i <= end_sub; i++) {
  3917.             if (parsedat[i] == IAC)
  3918.                 break;
  3919.             strTmp[i-5] = parsedat[i];
  3920.             strTmp[i-4] = 0;
  3921.         }
  3922.  
  3923.         if (!strTmp[0])
  3924.             strcpy(strTmp, "Authentication rejected by remote machine!");
  3925.         printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
  3926.         krb4_errno = -1;
  3927.         makestr(&krb4_errmsg,strTmp);
  3928.         auth_finished(AUTH_REJECT);
  3929.         return AUTH_FAILURE;
  3930.     }
  3931.  
  3932.     if (parsedat[4] == KRB_ACCEPT) {
  3933.         int net_len;
  3934.         if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
  3935.             ckmakmsg(strTmp,sizeof(strTmp),"Kerberos V4 accepts you as ",
  3936.                       szUserName,NULL,NULL);
  3937.             printf("%s\r\n",strTmp);
  3938.             accept_complete = 1;
  3939.             krb4_errno = 0;
  3940.             makestr(&krb4_errmsg,strTmp);
  3941.             auth_finished(AUTH_USER);
  3942.             return AUTH_SUCCESS;
  3943.         }
  3944.  
  3945.         if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
  3946.             printf("Kerberos V4 authentication failed!\r\n");
  3947.             ckstrncpy(strTmp,
  3948.         "Kerberos V4 accepted you, but didn't provide mutual authentication",
  3949.                        sizeof(strTmp));
  3950.             printf("%s\r\n",strTmp);
  3951.             krb4_errno = -1;
  3952.             makestr(&krb4_errmsg,strTmp);
  3953.             auth_finished(AUTH_REJECT);
  3954.             return AUTH_FAILURE;
  3955.         }
  3956.  
  3957. #ifndef REMOVE_FOR_EXPORT
  3958. #ifdef CK_ENCRYPTION
  3959.         SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
  3960.  
  3961.         /* We have sent the decrypted session key to the host as a challenge */
  3962.         /* now encrypt it to restore it to its original valid DES key value */
  3963. #ifdef MIT_CURRENT
  3964.         kdata.data = k4_session_key;
  3965.         kdata.length = 8;
  3966.  
  3967.         encdata.ciphertext.data = k4_session_key;
  3968.         encdata.ciphertext.length = 8;
  3969.         encdata.enctype = ENCTYPE_UNKNOWN;
  3970.  
  3971.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
  3972.                                    0, 0, &kdata, &encdata)) {
  3973.             com_err("k4_auth_reply", code,
  3974.                      "while encrypting session_key");
  3975.             auth_finished(AUTH_REJECT);
  3976.             return AUTH_FAILURE;
  3977.         }
  3978. #else /* MIT_CURRENT */
  3979. #ifdef NT
  3980.         des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
  3981. #else /* NT */
  3982.         des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
  3983. #endif /* NT */
  3984.         ckhexdump(
  3985.             "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
  3986.              k4_session_key,
  3987.              8
  3988.                 );
  3989. #endif /* MIT_CURRENT */
  3990.  
  3991. #ifdef CK_SSL
  3992.         if (!(ssl_active_flag || tls_active_flag))
  3993. #endif /* CK_SSL */
  3994.         {
  3995.         /* And then use it to configure the encryption state machine. */
  3996.             skey.type = SK_DES;
  3997.             skey.length = 8;
  3998.             skey.data = k4_session_key;
  3999.             encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4000.         }
  4001. #endif /* ENCRYPTION */
  4002. #endif /* REMOVE_FOR_EXPORT */
  4003.         accept_complete = 1;
  4004.         ckmakmsg(strTmp,sizeof(strTmp),
  4005.                  "Kerberos V4 accepts you as ",szUserName,NULL,NULL);
  4006.         printf("%s\r\n",strTmp);
  4007.         krb4_errno = 0;
  4008.         makestr(&krb4_errmsg,strTmp);
  4009.         auth_finished(AUTH_USER);
  4010.         return AUTH_SUCCESS;
  4011.     }
  4012.  
  4013.     if (parsedat[4] == KRB4_RESPONSE) {
  4014.         if (end_sub < 12) {
  4015.             auth_finished(AUTH_REJECT);
  4016.             return AUTH_FAILURE;
  4017.         }
  4018.  
  4019.         ckhexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
  4020. #ifdef CK_ENCRYPTION
  4021.         ckhexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
  4022.  
  4023.         /* The datablock returned from the host should match the value */
  4024.         /* we stored in k4_challenge.                                  */
  4025.         if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
  4026.             printf("Kerberos V4 authentication failed!\r\n%s\r\n",
  4027.             "Remote machine is being impersonated!");
  4028.             krb4_errno = -1;
  4029.             makestr(&krb4_errmsg,"Remote machine is being impersonated!");
  4030.             auth_finished(AUTH_REJECT);
  4031.             return AUTH_FAILURE;
  4032.         }
  4033. #else /* ENCRYPTION */
  4034.         makestr(&krb4_errmsg,"Kermit built without support for encryption.");
  4035.         return AUTH_FAILURE;
  4036. #endif /* ENCRYPTION */
  4037.         mutual_complete = 1;
  4038.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  4039.                    sizeof(strTmp));
  4040.         printf("%s\r\n",strTmp);
  4041.         krb4_errno = 0;
  4042.         makestr(&krb4_errmsg,strTmp);
  4043.         auth_finished(AUTH_USER);
  4044.         return AUTH_SUCCESS;
  4045.     }
  4046.     auth_finished(AUTH_REJECT);
  4047.     return AUTH_FAILURE;
  4048. }
  4049.  
  4050. /*
  4051.  * Function: K4 parse authentication IS command
  4052.  *
  4053.  * Parameters:
  4054.  *  parsedat - the sub-command data.
  4055.  *
  4056.  *  end_sub - index of the character in the 'parsedat' array which
  4057.  *            is the last byte in a sub-negotiation
  4058.  *
  4059.  * Returns: Kerberos error code.
  4060.  */
  4061.  
  4062. static int
  4063. #ifdef CK_ANSIC
  4064. k4_auth_is(unsigned char *parsedat, int end_sub)
  4065. #else
  4066. k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  4067. #endif
  4068. {
  4069. #ifdef CK_ENCRYPTION
  4070.     Session_Key skey;
  4071. #ifdef MIT_CURRENT
  4072.     Block datablock, tmpkey;
  4073.     krb5_data kdata;
  4074.     krb5_enc_data encdata;
  4075.     krb5_error_code code;
  4076. #else /* MIT_CURRENT */
  4077.     Block datablock;
  4078. #endif /* MIT_CURRENT */
  4079. #endif  /* ENCRYPTION */
  4080.     char realm[REALM_SZ+1];
  4081.     char instance[INST_SZ];
  4082.     int r = 0;
  4083.     char * data = &parsedat[5];
  4084.     int    cnt = end_sub - 5;
  4085.     extern char myipaddr[];
  4086.     struct hostent *host;
  4087.     struct in_addr inaddr;
  4088.     int i;
  4089.  
  4090.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  4091.         debug(F110,"k4_auth_is","Not kerberos v4",0);
  4092.         auth_finished(AUTH_REJECT);
  4093.         return AUTH_FAILURE;
  4094.     }
  4095.  
  4096.     switch (parsedat[4]) {
  4097.     case KRB_AUTH:
  4098.         debug(F110,"k4_auth_is","KRB_AUTH",0);
  4099.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ+1);
  4100.         if (realm[0] == '\0') {
  4101.             SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
  4102.             printf("\r\n? Kerberos 4 - No Local Realm\r\n");
  4103.             debug(F110,"k4_auth_is","No local realm",0);
  4104.             krb4_errno = -1;
  4105.             makestr(&krb4_errmsg,"No local realm");
  4106.             auth_finished(AUTH_REJECT);
  4107.             return AUTH_FAILURE;
  4108.         }
  4109.         debug(F110,"k4_auth_is",realm,0);
  4110.         if ( cnt < sizeof(k4_auth.dat) ) {
  4111.             k4_auth.length = cnt;
  4112.             memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
  4113.         } else
  4114.             k4_auth.length = 0;
  4115.         ckhexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
  4116.  
  4117.         /* Get Instance */
  4118.         inaddr.s_addr = inet_addr(myipaddr);
  4119.         host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
  4120.         if ( host ) {
  4121. #ifdef HADDRLIST
  4122.             host = ck_copyhostent(host);
  4123. #endif /* HADDRLIST */
  4124.             ckstrncpy(instance,host->h_name,INST_SZ);
  4125.             for ( i=0;i<INST_SZ;i++ ) {
  4126.                 if ( instance[i] == '.' )
  4127.                     instance[i] = '\0';
  4128.                 else
  4129.                     instance[i] = tolower(instance[i]);
  4130.             }
  4131.         } else {
  4132.             instance[0] = '*';
  4133.             instance[1] = 0;
  4134.         }
  4135.  
  4136.         if (r = krb_rd_req(&k4_auth,
  4137.                             krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  4138.                             instance, 0, &k4_adat, k4_keytab)) {
  4139.  
  4140.             ckhexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
  4141.             krb_kntoln(&k4_adat, k4_name);
  4142.             ckmakmsg(strTmp,sizeof(strTmp),
  4143.                      "Kerberos failed him as ", k4_name,NULL,NULL);
  4144.             printf("%s\r\n",strTmp);
  4145.             krb4_errno = r;
  4146.             makestr(&krb4_errmsg,strTmp);
  4147.             SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
  4148.             auth_finished(AUTH_REJECT);
  4149.             return AUTH_FAILURE;
  4150.         }
  4151.  
  4152. #ifdef CK_ENCRYPTION
  4153.         memcpy((void *)k4_session_key, (void *)k4_adat.session,
  4154.                 sizeof(Block));                 /* safe */
  4155.         ckhexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
  4156. #endif /* ENCRYPTION */
  4157.         krb_kntoln(&k4_adat, k4_name);
  4158.  
  4159.         ckstrncpy(szUserNameAuthenticated,k4_name,UIDBUFLEN);
  4160.         if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
  4161.             SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
  4162.             if ( !strcmp(k4_name,szUserNameRequested) )
  4163.                 auth_finished(AUTH_VALID);
  4164.             else
  4165.                 auth_finished(AUTH_USER);
  4166.             accept_complete = 1;
  4167.         }
  4168.         else {
  4169.             SendK4AuthSB(KRB_REJECT,
  4170.                   (void *)"user is not authorized", -1);
  4171.             auth_finished(AUTH_REJECT);
  4172.             krb4_errno = r;
  4173.             makestr(&krb4_errmsg,"user is not authorized");
  4174.             return(AUTH_FAILURE);
  4175.         }
  4176.         break;
  4177.  
  4178.     case KRB4_CHALLENGE:
  4179.         debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
  4180. #ifndef CK_ENCRYPTION
  4181.         SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  4182. #else   /* ENCRYPTION */
  4183.         if (!VALIDKEY(k4_session_key)) {
  4184.             /*
  4185.             * We don't have a valid session key, so just
  4186.             * send back a response with an empty session
  4187.             * key.
  4188.             */
  4189.             SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  4190.             mutual_complete = 1;
  4191.             break;
  4192.         }
  4193.  
  4194.         /*
  4195.         * Initialize the random number generator since it's
  4196.         * used later on by the encryption routine.
  4197.         */
  4198. #ifdef MIT_CURRENT
  4199.         kdata.data = k4_session_key;
  4200.         kdata.length = 8;
  4201.  
  4202.         if (code = krb5_c_random_seed(k5_context, &kdata)) {
  4203.             com_err("k4_auth_is", code,
  4204.                      "while seeding random number generator");
  4205.             auth_finished(AUTH_REJECT);
  4206.             return AUTH_FAILURE;
  4207.         }
  4208.  
  4209.         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
  4210.         /*
  4211.         * Take the received encrypted challenge, and encrypt
  4212.         * it again to get a unique session_key for the
  4213.         * ENCRYPT option.
  4214.         */
  4215.         k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  4216.         k4_krbkey.length = 8;
  4217.         k4_krbkey.contents = k4_session_key;
  4218.  
  4219.         kdata.data = datablock;
  4220.         kdata.length = 8;
  4221.  
  4222.         encdata.ciphertext.data = tmpkey;
  4223.         encdata.ciphertext.length = 8;
  4224.         encdata.enctype = ENCTYPE_UNKNOWN;
  4225.  
  4226.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  4227.                                    &kdata, &encdata)) {
  4228.             com_err("k4_auth_is", code, "while encrypting random key");
  4229.             auth_finished(AUTH_REJECT);
  4230.             return AUTH_FAILURE;
  4231.         }
  4232.  
  4233. #ifdef CK_SSL
  4234.         if (!(ssl_active_flag || tls_active_flag))
  4235. #endif /* CK_SSL */
  4236.         {
  4237.             skey.type = SK_DES;
  4238.             skey.length = 8;
  4239.             skey.data = tmpkey;
  4240.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4241.         }
  4242.         /*
  4243.         * Now decrypt the received encrypted challenge,
  4244.         * increment by one, re-encrypt it and send it back.
  4245.         */
  4246.         encdata.ciphertext.data = datablock;
  4247.         encdata.ciphertext.length = 8;
  4248.         encdata.enctype = ENCTYPE_UNKNOWN;
  4249.  
  4250.         kdata.data = k4_challenge;
  4251.         kdata.length = 8;
  4252.  
  4253.         if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  4254.                                    &encdata, &kdata)) {
  4255.             com_err("k4_auth_is", code, "while decrypting challenge");
  4256.             auth_finished(AUTH_REJECT);
  4257.             return AUTH_FAILURE;
  4258.         }
  4259. #else /* MIT_CURRENT */
  4260.         des_set_random_generator_seed(k4_session_key);
  4261.         r = des_key_sched(k4_session_key, k4_sched);
  4262.         if ( r == -1 ) {
  4263.             printf("?Invalid DES key specified in credentials\r\n");
  4264.             debug(F110,"auth_is CHALLENGE",
  4265.                    "invalid DES Key specified in credentials",0);
  4266.         } else if ( r == -2 ) {
  4267.             printf("?Weak DES key specified in credentials\r\n");
  4268.             debug(F110,"auth_is CHALLENGE",
  4269.                    "weak DES Key specified in credentials",0);
  4270.         } else if ( r != 0 ) {
  4271.             printf("?DES Key Schedule not set by credentials\r\n");
  4272.             debug(F110,"auth_is CHALLENGE",
  4273.                    "DES Key Schedule not set by credentials",0);
  4274.         }
  4275.         ckhexdump("auth_is schedule",k4_sched,8*16);
  4276.  
  4277.         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
  4278.         ckhexdump("auth_is challege",datablock,sizeof(Block));
  4279.  
  4280.         /*
  4281.         * Take the received encrypted challenge, and encrypt
  4282.         * it again to get a unique k4_session_key for the
  4283.         * ENCRYPT option.
  4284.         */
  4285. #ifdef NT
  4286.         des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
  4287. #else /* NT */
  4288.         des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
  4289. #endif /* NT */
  4290.         ckhexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
  4291.                  k4_session_key,8);
  4292.  
  4293. #ifdef CK_SSL
  4294.         if (!(ssl_active_flag || tls_active_flag))
  4295. #endif /* CK_SSL */
  4296.         {
  4297.             skey.type = SK_DES;
  4298.             skey.length = 8;
  4299.             skey.data = k4_session_key;
  4300.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4301.         }
  4302.         /*
  4303.         * Now decrypt the received encrypted challenge,
  4304.         * increment by one, re-encrypt it and send it back.
  4305.         */
  4306. #ifdef NT
  4307.         des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
  4308. #else /* NT */
  4309.         des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
  4310. #endif /* NT */
  4311.         ckhexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
  4312.                  k4_session_key,8);
  4313. #endif /* MIT_CURRENT */
  4314.         for (r = 7; r >= 0; r--) {
  4315.             register int t;
  4316.             t = (unsigned int)k4_challenge[r] + 1;
  4317.             k4_challenge[r] = t;        /* ignore overflow */
  4318.             if (t < 256)                /* if no overflow, all done */
  4319.                 break;
  4320.         }
  4321.         ckhexdump("auth_is k4_challenge+1",k4_challenge,8);
  4322.  
  4323. #ifdef MIT_CURRENT
  4324.         kdata.data = k4_challenge;
  4325.         kdata.length = 8;
  4326.  
  4327.         encdata.ciphertext.data = k4_challenge;
  4328.         encdata.ciphertext.length = 8;
  4329.         encdata.enctype = ENCTYPE_UNKNOWN;
  4330.  
  4331.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  4332.                                    &kdata, &encdata)) {
  4333.             com_err("k4_auth_is", code, "while decrypting challenge");
  4334.             auth_finished(AUTH_REJECT);
  4335.             return AUTH_FAILURE;
  4336.         }
  4337. #else /* MIT_CURRENT */
  4338. #ifdef NT
  4339.         des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  4340. #else /* NT */
  4341.         des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  4342. #endif /* NT */
  4343.         ckhexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
  4344.                  k4_challenge,8);
  4345.  
  4346. #endif /* MIT_CURRENT */
  4347.         SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
  4348. #endif  /* ENCRYPTION */
  4349.         mutual_complete = 1;
  4350.         break;
  4351.  
  4352.     default:
  4353.         if (1)
  4354.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  4355.         SendK4AuthSB(KRB_REJECT, 0, 0);
  4356.         return(AUTH_FAILURE);
  4357.     }
  4358.     krb4_errno = r;
  4359.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  4360.     return(AUTH_SUCCESS);
  4361. }
  4362. #endif /* KRB4 */
  4363.  
  4364. #ifdef KRB5
  4365. int
  4366. ck_krb5_autoget_TGT(char * realm)
  4367. {
  4368.     extern struct krb_op_data krb_op;
  4369.     extern struct krb5_init_data krb5_init;
  4370.     char passwd[PWD_SZ];
  4371.     char prompt[64];
  4372.     char * saverealm=NULL;
  4373.     int  rc = -1;
  4374.     extern char * k5prprompt;
  4375.     extern char * k5pwprompt;
  4376.  
  4377.     ini_kerb();         /* Place defaults in above structs */
  4378.     passwd[0] = '\0';
  4379.  
  4380.     if ( krb5_init.principal == NULL ||
  4381.          krb5_init.principal[0] == '\0') {
  4382.         int ok = uq_txt(NULL,k5prprompt && k5prprompt[0] ? k5prprompt :
  4383.                   "Kerberos 5 Principal: ",2,NULL,passwd,PWD_SZ-1,NULL,
  4384.             DEFAULT_UQ_TIMEOUT);
  4385.         if ( ok && passwd[0] )
  4386.             makestr(&krb5_init.principal,passwd);
  4387.         else
  4388.             return(0);
  4389.     }
  4390.  
  4391.     /* Save realm in init structure so it can be restored */
  4392.     if ( realm ) {
  4393.         saverealm = krb5_init.realm;
  4394.         krb5_init.realm = realm;
  4395.     }
  4396.  
  4397.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  4398.         int ok;
  4399.         if ( k5pwprompt && k5pwprompt[0] &&
  4400.              (strlen(k5pwprompt) + strlen(krb5_init.principal) +
  4401.               strlen(krb5_init.realm) - 4) < sizeof(prompt)) {
  4402.             sprintf(prompt,k5pwprompt,krb5_init.principal,krb5_init.realm);
  4403.         } else
  4404.         ckmakxmsg(prompt,sizeof(prompt),
  4405.                   k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  4406.                   "Kerberos 5 Password for ",
  4407.                   krb5_init.principal,"@",krb5_init.realm,": ",
  4408.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL
  4409.                  );
  4410.         ok = uq_txt(NULL,prompt,2,NULL,passwd,PWD_SZ-1,NULL,
  4411.             DEFAULT_UQ_TIMEOUT);
  4412.         if ( !ok )
  4413.             passwd[0] = '\0';
  4414.     } else {
  4415.         ckstrncpy(passwd,(char *)pwbuf,sizeof(passwd));
  4416. #ifdef OS2
  4417.         if ( pwcrypt )
  4418.             ck_encrypt((char *)passwd);
  4419. #endif /* OS2 */
  4420.     }
  4421.  
  4422.     if ( passwd[0] ) {
  4423.         extern struct krb4_init_data krb4_init;
  4424.         char * savek4realm=NULL;
  4425.  
  4426.         makestr(&krb5_init.password,passwd);
  4427.  
  4428.         if ( krb5_d_getk4 ) {
  4429.             krb5_init.getk4 = 1;
  4430.             makestr(&krb4_init.principal,krb5_init.principal);
  4431.             makestr(&krb4_init.password,passwd);
  4432.             if ( realm ) {
  4433.                 savek4realm = krb4_init.realm;
  4434.                 krb4_init.realm = realm;
  4435.             }
  4436.             rc = ck_krb5_initTGT(&krb_op, &krb5_init,&krb4_init);
  4437.  
  4438.             if ( savek4realm )
  4439.                 krb4_init.realm = savek4realm;
  4440.             free(krb4_init.password);
  4441.             krb4_init.password = NULL;
  4442.         } else {
  4443.             rc = ck_krb5_initTGT(&krb_op, &krb5_init,NULL);
  4444.         }
  4445.  
  4446.         free(krb5_init.password);
  4447.         krb5_init.password = NULL;
  4448.  
  4449.         memset(passwd,0,PWD_SZ);
  4450.     }
  4451.  
  4452.     /* restore realm to init structure if needed */
  4453.     if ( saverealm )
  4454.         krb5_init.realm = saverealm;
  4455.     return(rc == 0);
  4456. }
  4457.  
  4458. static krb5_error_code
  4459. #ifdef CK_ANSIC
  4460. k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
  4461.                char * cc_name )
  4462. #else  /* CK_ANSIC */
  4463. k5_get_ccache(k5_context, p_ccache, cc_name)
  4464.     krb5_context k5_context;
  4465.     krb5_ccache * p_ccache;
  4466.     char * cc_name;
  4467. #endif /* CK_ANSIC */
  4468. {
  4469.     krb5_error_code r=0;
  4470.     char cc_tmp[CKMAXPATH+1];
  4471.     const char * def_name = NULL;
  4472.  
  4473. #ifndef HEIMDAL
  4474.     if ( cc_name ) {
  4475.         if ( strncmp("FILE:",cc_name,5) &&
  4476.              strncmp("MEMORY:",cc_name,7) &&
  4477.              strncmp("API:",cc_name,4) &&
  4478.              strncmp("STDIO:",cc_name,6) &&
  4479.          strncmp("MSLSA:",cc_name,6))
  4480. #ifdef NT
  4481.             ckmakmsg(cc_tmp,CKMAXPATH,"API:",cc_name,NULL,NULL);
  4482. #else /* NT */
  4483.             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",cc_name,NULL,NULL);
  4484. #endif /* NT */
  4485.         else {
  4486.             ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
  4487.         }
  4488.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  4489.         if (r != 0) {
  4490.             com_err("k5_get_ccache resolving ccache",r,
  4491.                      cc_tmp);
  4492.         } else {
  4493.             /* Make sure GSSAPI sees the same cache we are using */
  4494.             char buf[128];
  4495.             ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
  4496.             putenv(buf);
  4497.         }
  4498.     } else if ( krb5_d_cc ) {
  4499.         if ( strncmp("FILE:",krb5_d_cc,5) &&
  4500.              strncmp("MEMORY:",krb5_d_cc,7) &&
  4501.              strncmp("API:",krb5_d_cc,4) &&
  4502.              strncmp("STDIO:",krb5_d_cc,6) &&
  4503.          strncmp("MSLSA:", krb5_d_cc,6))
  4504. #ifdef NT
  4505.             ckmakmsg(cc_tmp,CKMAXPATH,"API:",krb5_d_cc,NULL,NULL);
  4506. #else /* NT */
  4507.             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",krb5_d_cc,NULL,NULL);
  4508. #endif /* NT */
  4509.         else {
  4510.             ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
  4511.         }
  4512.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  4513.         if (r != 0) {
  4514.             com_err("k5_get_ccache resolving ccache",r,
  4515.                      krb5_d_cc);
  4516.         } else {
  4517.             /* Make sure GSSAPI sees the same cache we are using */
  4518.             char buf[128];
  4519.             ckmakmsg((char *)buf,128,"KRB5CCNAME=",cc_tmp,NULL,NULL);
  4520.             putenv(buf);
  4521.         }
  4522.     } else
  4523. #endif /* HEIMDAL */
  4524.     {
  4525.         if ((r = krb5_cc_default(k5_context, p_ccache))) {
  4526.             com_err("k5_get_ccache",r,"while getting default ccache");
  4527.         }
  4528.     }
  4529.     /* do not set krb5_errno/krb5_errmsg here since the value returned */
  4530.     /* is being passed internally within the krb5 functions.           */
  4531.     return(r);
  4532. }
  4533.  
  4534.  
  4535. char *
  4536. ck_krb5_realmofhost(char *host)
  4537. {
  4538.     char ** realmlist=NULL;
  4539.     krb5_context private_context=NULL;
  4540.     static char * realm = NULL;
  4541.  
  4542.     if ( !host )
  4543.         return NULL;
  4544.  
  4545.     if ( realm ) {
  4546.         free(realm);
  4547.         realm = NULL;
  4548.     }
  4549.  
  4550.     /* create private_context */
  4551.     if (krb5_init_context(&private_context)) {
  4552.         debug(F110,"ck_krb5_realmofhost()","unable to init_context",0);
  4553.         return(NULL);
  4554.     }
  4555.  
  4556.     krb5_get_host_realm(private_context,host,&realmlist);
  4557.     if (realmlist && realmlist[0]) {
  4558.         makestr(&realm,realmlist[0]);
  4559.         krb5_free_host_realm(private_context,realmlist);
  4560.         realmlist = NULL;
  4561.     }
  4562.  
  4563.     if ( private_context ) {
  4564.         krb5_free_context(private_context);
  4565.         private_context = NULL;
  4566.     }
  4567.  
  4568.     if (ckstrchr(realm,'.') == NULL) {
  4569.         int n = 0;
  4570.         char * p = host;
  4571.         while ( (p = ckstrchr(p,'.')) != NULL ) {
  4572.             n++;
  4573.             p++;
  4574.         }
  4575.         if (n == 1) {
  4576.             makestr(&realm,host);
  4577.             ckupper(realm);
  4578.         } else {
  4579.             free(realm);
  4580.             realm = NULL;
  4581.         }
  4582.     }
  4583.     return(realm);
  4584. }
  4585.  
  4586. /*
  4587.  *
  4588.  * K5_auth_send - gets authentication bits we need to send to KDC.
  4589.  *
  4590.  * Code lifted from telnet sample code in the appl directory.
  4591.  *
  4592.  * Result is left in k5_auth
  4593.  *
  4594.  * Returns: 0 on failure, 1 on success
  4595.  *
  4596.  */
  4597.  
  4598. static int
  4599. #ifdef CK_ANSIC
  4600. k5_auth_send(int how, int encrypt, int forward)
  4601. #else
  4602. k5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
  4603. #endif
  4604. {
  4605.     krb5_error_code r=0;
  4606.     krb5_ccache ccache=NULL;
  4607. #ifndef HEIMDAL
  4608.     krb5_creds creds;
  4609. #endif /* HEIMDAL */
  4610.     krb5_creds * new_creds=NULL;
  4611. #ifdef CK_ENCRYPTION
  4612.     krb5_keyblock *newkey = 0;
  4613. #endif /* CK_ENCRYPTION */
  4614.     krb5_flags ap_opts, auth_flags;
  4615.     char type_check[32];
  4616.     krb5_data checksum;
  4617.     int len=0;
  4618.     char * realm = NULL;
  4619.     char tgt[256];
  4620.  
  4621.     realm = ck_krb5_realmofhost(szHostName);
  4622.     if (!realm) {
  4623.         ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
  4624.         ckstrncat(strTmp, szHostName,AUTHTMPBL);
  4625.         ckstrncat(strTmp, "\"",AUTHTMPBL);
  4626.         printf("?Kerberos 5 error: %s\r\n",strTmp);
  4627.         krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
  4628.         makestr(&krb5_errmsg,strTmp);
  4629.         return(0);
  4630.     }
  4631.  
  4632.     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  4633.     debug(F110,"k5_auth_send TGT",tgt,0);
  4634.     if ( krb5_autoget &&
  4635.          !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  4636.           (ck_krb5_is_tgt_valid() > 0)) )
  4637.         ck_krb5_autoget_TGT(realm);
  4638.  
  4639.     r = k5_get_ccache(k5_context,&ccache,NULL);
  4640.     if ( r ) {
  4641.         com_err(NULL, r, "while authorizing (0).");
  4642.         krb5_errno = r;
  4643.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4644.         return(0);
  4645.     }
  4646.  
  4647. #ifndef HEIMDAL
  4648.     memset((char *)&creds, 0, sizeof(creds));
  4649.     if (r = krb5_sname_to_principal(k5_context, szHostName,
  4650.                                 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4651.                                 KRB5_NT_SRV_HST, &creds.server)) {
  4652.         com_err(NULL, r, "while authorizing (1).");
  4653.         krb5_errno = r;
  4654.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4655.         return(0);
  4656.     }
  4657.  
  4658.     if (forward_flag) {
  4659.         if (fwd_server) {
  4660.             krb5_free_principal(k5_context,fwd_server);
  4661.             fwd_server = NULL;
  4662.         }
  4663.         krb5_copy_principal(k5_context,creds.server,&fwd_server);
  4664.     }
  4665.  
  4666.     r = krb5_cc_get_principal(k5_context, ccache, &creds.client);
  4667.     if (r) {
  4668.         com_err(NULL, r, "while authorizing (2).");
  4669.         krb5_free_cred_contents(k5_context, &creds);
  4670.         krb5_errno = r;
  4671.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4672.         return(0);
  4673.     }
  4674.  
  4675.     if (szUserName[0] == '\0') {                /* Get user name now */
  4676.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4677.         if ( len < sizeof(szUserName) ) {
  4678.             memcpy(szUserName,
  4679.                     krb5_princ_component(k5_context, creds.client, 0)->data,
  4680.                     len);                       /* safe */
  4681.         } else
  4682.             len = 0;
  4683.         szUserName[len] = '\0';
  4684.     } else {
  4685.         char * name = NULL;
  4686.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4687.         if ( len == strlen(szUserName) ) {
  4688.             name = krb5_princ_component(k5_context, creds.client, 0)->data;
  4689. #ifdef OS2
  4690.             if ( !strnicmp(szUserName,name,len) )
  4691.                 memcpy(szUserName,name,len);    /* safe */
  4692. #endif /* OS2 */
  4693.         }
  4694.     }
  4695.     if ( tn_auth_krb5_des_bug ) {   /* !ALLOW_KRB_3DES_ENCRYPT */
  4696.         /* Not sure if this is necessary anymore.  What impact does it have
  4697.          * on Win2000 TGTs that use DES_CBC_MD5 or RC4_HMAC?
  4698.          *
  4699.          * This prevents using 3DES Service Tickets.
  4700.          */
  4701.         creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
  4702.     }
  4703.  
  4704.     if (r = krb5_get_credentials(k5_context, 0,
  4705.                                   ccache, &creds, &new_creds)) {
  4706.         com_err(NULL, r, "while authorizing (3).");
  4707.         krb5_free_cred_contents(k5_context, &creds);
  4708.         krb5_errno = r;
  4709.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4710.         return(0);
  4711.     }
  4712. #endif /* HEIMDAL */
  4713.  
  4714.     if (auth_context) {
  4715.         krb5_auth_con_free(k5_context, auth_context);
  4716.         auth_context = 0;
  4717.     }
  4718.     if (r = krb5_auth_con_init(k5_context, &auth_context)) {
  4719.         com_err(NULL, r, "while initializing auth context");
  4720.         krb5_errno = r;
  4721.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4722.         return(0);
  4723.     }
  4724.  
  4725.     /* UPDATE for START_TLS.  AUTH_ENCRYPT_START_TLS and inclusion of */
  4726.     /* client and then server finished messages.                      */
  4727.  
  4728.     type_check[0] = AUTHTYPE_KERBEROS_V5;
  4729.     type_check[1] = AUTH_CLIENT_TO_SERVER |
  4730.         (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
  4731.         (encrypt) |
  4732.         (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
  4733. #ifdef CK_SSL
  4734.     if (encrypt == AUTH_ENCRYPT_START_TLS) {
  4735.         ssl_get_client_finished(&type_check[2],12);
  4736.         ssl_get_server_finished(&type_check[14],12);
  4737.     }
  4738. #endif /* CK_SSL */
  4739.  
  4740. #ifndef HEIMDAL
  4741.     checksum.magic = KV5M_DATA;
  4742. #endif /* HEIMDAL */
  4743.     checksum.length =
  4744. #ifdef CK_SSL
  4745.         (encrypt == AUTH_ENCRYPT_START_TLS) ? 26 :
  4746. #endif /* CK_SSL */
  4747.         2;
  4748.     checksum.data = (char *)&type_check;
  4749.  
  4750.     ap_opts = 0;
  4751.     if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
  4752.         ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
  4753.  
  4754. #ifdef HEIMDAL
  4755.     r = krb5_auth_setkeytype(k5_context, auth_context, KEYTYPE_DES);
  4756.     if (r)
  4757.         com_err(NULL, r, "while setting auth keytype");
  4758.     r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context, &ttyfd);
  4759.     if (r)
  4760.         com_err(NULL, r, "while setting auth addrs");
  4761.     r = krb5_mk_req(k5_context, &auth_context, ap_opts,
  4762.                     krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4763.                     szHostName, &checksum, ccache, &k5_auth);
  4764.     if (r)
  4765.         com_err(NULL, r, "while making request");
  4766. #else /* HEIMDAL */
  4767.     auth_flags = KRB5_AUTH_CONTEXT_RET_TIME;
  4768. #ifdef CK_ENCRYPTION
  4769.     ap_opts |= AP_OPTS_USE_SUBKEY;
  4770. #endif /* CK_ENCRYPTION */
  4771. #ifdef TLS_VERIFY
  4772.     if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  4773.         auth_flags |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
  4774.         if (!krb5_d_no_addresses)
  4775.             r = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  4776.                                  KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
  4777.     }
  4778. #endif /* CK_SSL */
  4779.     krb5_auth_con_setflags(k5_context, auth_context, auth_flags);
  4780.     r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
  4781.                               &checksum, new_creds, &k5_auth);
  4782. #endif /* HEIMDAL */
  4783.  
  4784. #ifdef CK_ENCRYPTION
  4785.     if (!r) {
  4786.         r = krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
  4787.         if (r)
  4788.             r = krb5_auth_con_getkey(k5_context, auth_context, &newkey);
  4789.  
  4790.         if (k5_session_key) {
  4791.             krb5_free_keyblock(k5_context, k5_session_key);
  4792.             k5_session_key = 0;
  4793.         }
  4794.     }
  4795.     if (newkey) {
  4796.         /*
  4797.         * keep the key in our private storage, but don't use it
  4798.         * yet---see kerberos5_reply() below
  4799.         */
  4800. #ifdef HEIMDAL
  4801.         if ((newkey->keytype == ETYPE_DES_CBC_CRC) ||
  4802.              (newkey->keytype == ETYPE_DES_CBC_MD5) ||
  4803.              (newkey->keytype == ETYPE_DES_CBC_MD4))
  4804.         {
  4805.             debug(F111,"k5_auth_send()","newkey->keytype",newkey->keytype);
  4806.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4807.         }
  4808. #else /* HEIMDAL */
  4809.         /* look for all possible DES keys first - just for compatibility */
  4810.         /* other key types are much less likely to be available          */
  4811.         if ((newkey->enctype == ENCTYPE_DES_CBC_CRC) ||
  4812.              (newkey->enctype == ENCTYPE_DES_CBC_MD5) ||
  4813.              (newkey->enctype == ENCTYPE_DES_CBC_MD4))
  4814.         {
  4815.             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
  4816.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4817.         }
  4818.         else if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
  4819.                  (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
  4820.         {
  4821.             /* use the session key in credentials instead */
  4822.             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
  4823.                    new_creds->keyblock.enctype);
  4824.             krb5_copy_keyblock(k5_context,
  4825.                                 &new_creds->keyblock, &k5_session_key);
  4826.         }
  4827.         else if (newkey->enctype != 0)
  4828.         {
  4829.             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
  4830.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4831.         }
  4832.         else if (new_creds->keyblock.enctype != 0)
  4833.         {
  4834.             /* use the session key in credentials instead */
  4835.             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
  4836.                    new_creds->keyblock.enctype);
  4837.             krb5_copy_keyblock(k5_context,
  4838.                                 &new_creds->keyblock, &k5_session_key);
  4839.         }
  4840.         else {
  4841.             debug(F110,"k5_auth_send()","NO KEY in newkey",0);
  4842.         }
  4843. #endif /* HEIMDAL */
  4844.         krb5_free_keyblock(k5_context, newkey);
  4845.     }
  4846. #endif /* CK_ENCRYPTION */
  4847. #ifndef HEIMDAL
  4848.     krb5_free_cred_contents(k5_context, &creds);
  4849.     krb5_free_creds(k5_context, new_creds);
  4850. #endif /* HEIMDAL */
  4851.     krb5_cc_close(k5_context,ccache);
  4852.  
  4853.     if (r) {
  4854.         com_err(NULL, r, "while authorizing (4).");
  4855.         krb5_errno = r;
  4856.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4857.         return(0);
  4858.     }
  4859.     krb5_errno = 0;
  4860.     makestr(&krb5_errmsg,"OK");
  4861.     return(1);
  4862. }
  4863.  
  4864. /*
  4865.  * K5_auth_reply -- checks the reply for mutual authentication.
  4866.  */
  4867. static int
  4868. #ifdef CK_ANSIC
  4869. k5_auth_reply(int how, unsigned char *data, int cnt)
  4870. #else
  4871. k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  4872. #endif
  4873. {
  4874. #ifdef CK_ENCRYPTION
  4875.     Session_Key skey;
  4876. #endif /* CK_ENCRYPTION */
  4877.  
  4878.     data += 4;                                  /* Point to status byte */
  4879.     cnt -=5;
  4880.  
  4881.     switch (*data++) {
  4882.     case KRB_REJECT:
  4883.         if (cnt > 0) {
  4884.             char *s;
  4885.             int len;
  4886.             ckstrncpy(strTmp,"Kerberos V5 refuses authentication because\r\n",
  4887.                       sizeof(strTmp));
  4888.             len = strlen(strTmp);
  4889.             if ( len + cnt < sizeof(strTmp) ) {
  4890.                 s = strTmp + strlen(strTmp);
  4891.                 memcpy(s, data, cnt);           /* safe */
  4892.                 s[cnt] = 0;
  4893.             }
  4894.         } else
  4895.             ckstrncpy(strTmp,"Kerberos V5 refuses authentication",
  4896.                       sizeof(strTmp));
  4897.         krb5_errno = -1;
  4898.         makestr(&krb5_errmsg,strTmp);
  4899.         printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4900.         auth_finished(AUTH_REJECT);
  4901.         return AUTH_FAILURE;
  4902.  
  4903.     case KRB_ACCEPT:
  4904.         if (!mutual_complete) {
  4905.             if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
  4906.                 ckstrncpy(strTmp,
  4907.                           "Kerberos V5 accepted you, but didn't provide"
  4908.                           " mutual authentication",sizeof(strTmp));
  4909.                 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4910.                 krb5_errno = -1;
  4911.                 makestr(&krb5_errmsg,strTmp);
  4912.                 auth_finished(AUTH_REJECT);
  4913.                 return AUTH_FAILURE;
  4914.             }
  4915.  
  4916. #ifdef CK_ENCRYPTION
  4917.             if (k5_session_key) {
  4918.                 if ( tn_auth_krb5_des_bug ) {   /* !ALLOW_KRB_3DES_ENCRYPT */
  4919.                     skey.type = SK_DES;
  4920.                     skey.length = 8;
  4921. #ifdef HEIMDAL
  4922.                     skey.data = k5_session_key->keyvalue.data;
  4923. #else /* HEIMDAL */
  4924.                     skey.data = k5_session_key->contents;
  4925. #endif /* HEIMDAL */
  4926.                 } else {
  4927. #ifdef HEIMDAL
  4928.                     switch ( k5_session_key->keytype ) {
  4929.                     case ETYPE_DES_CBC_CRC:
  4930.                     case ETYPE_DES_CBC_MD5:
  4931.                     case ETYPE_DES_CBC_MD4:
  4932.                         skey.type = SK_DES;
  4933.                         skey.length = 8;
  4934.                         break;
  4935.                     default:
  4936.                         skey.type = SK_GENERIC;
  4937.                         skey.length = k5_session_key->length;
  4938.                         encrypt_dont_support(ENCTYPE_DES_CFB64);
  4939.                         encrypt_dont_support(ENCTYPE_DES_OFB64);
  4940.                     }
  4941.                     skey.data = k5_session_key->keyvalue.data;
  4942. #else /* HEIMDAL */
  4943.                     switch ( k5_session_key->enctype ) {
  4944.                     case ENCTYPE_DES_CBC_CRC:
  4945.                     case ENCTYPE_DES_CBC_MD5:
  4946.                     case ENCTYPE_DES_CBC_MD4:
  4947.                         skey.type = SK_DES;
  4948.                         skey.length = 8;
  4949.                     default:
  4950.                         skey.type = SK_GENERIC;
  4951.                         skey.length = k5_session_key->length;
  4952.                         encrypt_dont_support(ENCTYPE_DES_CFB64);
  4953.                         encrypt_dont_support(ENCTYPE_DES_OFB64);
  4954.                     }
  4955.                     skey.data = k5_session_key->contents;
  4956. #endif /* HEIMDAL */
  4957.                 }
  4958.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4959.             }
  4960. #endif /* CK_ENCRYPTION */
  4961.         }
  4962.         if ( cnt > 0 ) {
  4963.             char *s;
  4964.             int len;
  4965.             ckstrncpy(strTmp,"Kerberos V5 accepts you as ",sizeof(strTmp));
  4966.             len = strlen(strTmp);
  4967.             if ( len + cnt < sizeof(strTmp) ) {
  4968.                 s = strTmp + strlen(strTmp);
  4969.                 memcpy(s,data,cnt);
  4970.                 s[cnt] = 0;
  4971.             }
  4972.         }
  4973.         accept_complete = 1;
  4974.         printf("%s\r\n",strTmp);
  4975.  
  4976. #ifdef FORWARD
  4977.         if (forward_flag
  4978. #ifdef COMMENT
  4979.              /* Marc Horowitz <marc@mit.edu> has successfully argued
  4980.                 that it is indeed safe to send Forwarded credentials
  4981.                 to an untrusted host.
  4982.               */
  4983.              && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL
  4984. #endif /* COMMENT */
  4985.              )
  4986.             kerberos5_forward();
  4987. #endif /* FORWARD */
  4988.         krb5_errno = 0;
  4989.         makestr(&krb5_errmsg,strTmp);
  4990.         auth_finished(AUTH_USER);
  4991.         return AUTH_SUCCESS;
  4992.  
  4993.     case KRB5_RESPONSE:
  4994. #ifdef TLS_VERIFY
  4995.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
  4996.             !krb5_tls_verified) {
  4997.             printf(
  4998.     "Man in the middle attack detected.  Session terminated.\r\n");
  4999. #ifndef BETATEST
  5000.             netclos();
  5001. #endif /* BETATEST */
  5002.             krb5_errno = -1;
  5003.             makestr(&krb5_errmsg,"TLS not verified");
  5004.             auth_finished(AUTH_REJECT);
  5005.             return AUTH_FAILURE;
  5006.         }
  5007.         if((ssl_active_flag || tls_active_flag) &&
  5008.             (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5009.             printf("TLS session parameters verified by Kerberos 5\r\n");
  5010.         }
  5011. #endif /* TLS_VERIFY */
  5012.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  5013.             /* the rest of the reply should contain a krb_ap_rep */
  5014.             krb5_ap_rep_enc_part *reply;
  5015.             krb5_data inbuf;
  5016.             krb5_error_code r;
  5017.  
  5018.             inbuf.length = cnt;
  5019.             inbuf.data = (char *)data;
  5020.  
  5021.             if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
  5022.                 com_err(NULL, r, "while authorizing. (5)");
  5023.                 krb5_errno = r;
  5024.                 makestr(&krb5_errmsg,error_message(krb5_errno));
  5025.                 auth_finished(AUTH_REJECT);
  5026.                 return AUTH_FAILURE;
  5027.             }
  5028.             krb5_free_ap_rep_enc_part(k5_context, reply);
  5029.  
  5030. #ifdef CK_ENCRYPTION
  5031.             if (encrypt_flag && k5_session_key) {
  5032.                 if ( tn_auth_krb5_des_bug ) {   /* !ALLOW_KRB_3DES_ENCRYPT */
  5033.                     skey.type = SK_DES;
  5034.                     skey.length = 8;
  5035. #ifdef HEIMDAL
  5036.                     skey.data = k5_session_key->keyvalue.data;
  5037. #else /* HEIMDAL */
  5038.                     skey.data = k5_session_key->contents;
  5039. #endif /* HEIMDAL */
  5040.                 } else {
  5041. #ifdef HEIMDAL
  5042.                     switch ( k5_session_key->keytype ) {
  5043.                     case ETYPE_DES_CBC_CRC:
  5044.                     case ETYPE_DES_CBC_MD5:
  5045.                     case ETYPE_DES_CBC_MD4:
  5046.                         skey.type = SK_DES;
  5047.                         skey.length = 8;
  5048.                     default:
  5049.                         skey.type = SK_GENERIC;
  5050.                         skey.length = k5_session_key->length;
  5051.                     }
  5052.                     skey.data = k5_session_key->keyvalue.data;
  5053. #else /* HEIMDAL */
  5054.                     switch ( k5_session_key->enctype ) {
  5055.                     case ENCTYPE_DES_CBC_CRC:
  5056.                     case ENCTYPE_DES_CBC_MD5:
  5057.                     case ENCTYPE_DES_CBC_MD4:
  5058.                         skey.type = SK_DES;
  5059.                         skey.length = 8;
  5060.                         break;
  5061.                     default:
  5062.                         skey.type = SK_GENERIC;
  5063.                         skey.length = k5_session_key->length;
  5064.                     }
  5065.                     skey.data = k5_session_key->contents;
  5066. #endif /* HEIMDAL */
  5067.                 }
  5068.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  5069.             }
  5070. #endif /* ENCRYPTION */
  5071.             mutual_complete = 1;
  5072.         }
  5073.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  5074.                   sizeof(strTmp));
  5075.         krb5_errno = 0;
  5076.         makestr(&krb5_errmsg,strTmp);
  5077.         printf("%s\r\n",strTmp);
  5078.         auth_finished(AUTH_USER);
  5079.         return AUTH_SUCCESS;
  5080.  
  5081. #ifdef FORWARD
  5082.     case KRB5_FORWARD_ACCEPT:
  5083.         forwarded_tickets = 1;
  5084.         ckstrncpy(strTmp,"Remote machine has accepted forwarded credentials",
  5085.                   sizeof(strTmp));
  5086.         krb5_errno = 0;
  5087.         makestr(&krb5_errmsg,strTmp);
  5088.         printf("%s\r\n",strTmp);
  5089.         return AUTH_SUCCESS;
  5090.  
  5091.     case KRB5_FORWARD_REJECT:
  5092.         forwarded_tickets = 0;
  5093.         if (cnt > 0) {
  5094.             char *s;
  5095.             int len;
  5096.             len = ckstrncpy(strTmp,
  5097.                       "Kerberos V5 refuses forwarded credentials because ",
  5098.                        sizeof(strTmp));
  5099.             if ( len + cnt < sizeof(strTmp) ) {
  5100.                 s = strTmp + strlen(strTmp);
  5101.                 memcpy(s, data, cnt);
  5102.                 s[cnt] = 0;
  5103.             }
  5104.         } else
  5105.             ckstrncpy(strTmp, "Kerberos V5 refuses forwarded credentials",
  5106.                       sizeof(strTmp));
  5107.  
  5108.         printf("%s\r\n",strTmp);
  5109.         krb5_errno = -1;
  5110.         makestr(&krb5_errmsg,strTmp);
  5111.         return AUTH_SUCCESS;
  5112. #endif  /* FORWARD */
  5113.  
  5114. #ifdef TLS_VERIFY
  5115.     case KRB5_TLS_VERIFY:
  5116.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5117.             krb5_data reply, msg;
  5118.             char tls_verify[24];
  5119.             krb5_replay_data repdata;
  5120.             krb5_error_code r;
  5121.  
  5122.             ssl_get_server_finished(&tls_verify[0],12);
  5123.             ssl_get_client_finished(&tls_verify[12],12);
  5124.  
  5125.             reply.data = (char *)data;
  5126.             reply.length = cnt;
  5127.  
  5128.             krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  5129.                                    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
  5130.  
  5131.             if (r = krb5_rd_safe(k5_context,auth_context,&reply,&msg,&repdata))
  5132.               {
  5133.                 com_err("", r, "decoding tls verifier");
  5134.                 krb5_errno = r;
  5135.                 makestr(&krb5_errmsg,"TLS verify failure");
  5136.                 auth_finished(AUTH_REJECT);
  5137.                 return(AUTH_FAILURE);
  5138.             }
  5139.             if ( msg.length == 24 && !memcmp(msg.data,tls_verify,24) )
  5140.                  krb5_tls_verified = 1;
  5141.             krb5_free_data_contents(k5_context,&msg);
  5142.             if (krb5_tls_verified)
  5143.                 return(AUTH_SUCCESS);
  5144.         }
  5145.         printf("Man in the middle attack detected.  Session terminated.\r\n");
  5146.         netclos();
  5147.         krb5_errno = -1;
  5148.         makestr(&krb5_errmsg,"TLS verify failure");
  5149.         auth_finished(AUTH_REJECT);
  5150.         return(AUTH_FAILURE);
  5151. #endif /* CK_SSL */
  5152.  
  5153.     default:
  5154.         krb5_errno = -1;
  5155.         makestr(&krb5_errmsg,"Unknown reply type");
  5156.         auth_finished(AUTH_REJECT);
  5157.         return AUTH_FAILURE;                        /* Unknown reply type */
  5158.     }
  5159. }
  5160.  
  5161. #ifdef FORWARD
  5162. /* Decode, decrypt and store the forwarded creds in the local ccache. */
  5163. /* Needed for KRB5_FORWARD                                            */
  5164. static krb5_error_code
  5165. rd_and_store_for_creds(context, auth_context, inbuf, client)
  5166.     krb5_context context;
  5167.     krb5_auth_context auth_context;
  5168.     krb5_data *inbuf;
  5169.     krb5_const_principal client;
  5170. {
  5171.     krb5_creds ** creds=NULL;
  5172.     krb5_error_code retval;
  5173.     krb5_ccache ccache=NULL;
  5174.  
  5175. #ifdef HEIMDAL
  5176.     /*
  5177.     Heimdal Telnetd creates the cache file at this point and sets
  5178.     the KRB5CCNAME environment variable.
  5179.  
  5180.     struct passwd *pwd;
  5181.     char ccname[1024];
  5182.  
  5183.     pwd = getpwnam(szUserNameRequested);
  5184.     if (pwd == NULL)
  5185.         break;
  5186.     snprintf(ccname, sizeof(ccname)-1, "FILE:/tmp/krb5cc_%u",pwd->pw_uid);
  5187.     retval = krb5_cc_resolve(context,ccname,&ccache);
  5188.  
  5189.     chown(ccname + 5, pwd->pw_uid, -1);
  5190.     */
  5191. #endif /* HEIMDAL */
  5192.  
  5193.     if (retval = k5_get_ccache(context,&ccache,NULL))
  5194.         return(retval);
  5195.  
  5196. #ifdef HEIMDAL
  5197.     if ((retval = krb5_cc_initialize(context, ccache, client)))
  5198.         return(retval);
  5199.  
  5200.     if ((retval = krb5_rd_cred(context, auth_context, ccache, inbuf)))
  5201.         return(retval);
  5202. #else /* HEIMDAL */
  5203.     if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
  5204.         return(retval);
  5205.  
  5206.     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
  5207.         goto cleanup;
  5208.  
  5209.     if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
  5210.         goto cleanup;
  5211.  
  5212.     if ((retval = krb5_cc_close(context, ccache)))
  5213.         goto cleanup;
  5214.  
  5215.   cleanup:
  5216.     krb5_free_tgt_creds(context, creds);
  5217. #endif /* HEIMDAL */
  5218.     return retval;
  5219. }
  5220. #endif /* FORWARD */
  5221.  
  5222. /*
  5223.  *
  5224.  * K5_auth_is.
  5225.  *
  5226.  */
  5227.  
  5228. static int
  5229. #ifdef CK_ANSIC
  5230. k5_auth_is(int how, unsigned char *data, int cnt)
  5231. #else
  5232. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  5233. #endif
  5234. {
  5235.     int r = 0;
  5236.     krb5_principal server;
  5237.     krb5_keyblock *newkey = NULL;
  5238.     krb5_data outbuf;
  5239.     char errbuf[128]="";
  5240.     char *getenv();
  5241. #ifndef HEIMDAL
  5242.     krb5_authenticator *authenticator;
  5243.     krb5_keytab keytabid = 0;
  5244. #endif /* HEIMDAL */
  5245.     krb5_data inbuf;
  5246. #ifdef CK_ENCRYPTION
  5247.     Session_Key skey;
  5248. #endif /* CK_ENCRYPTION */
  5249.     char princ[256]="";
  5250.     int len;
  5251.  
  5252.     data += 4;                                  /* Point to status byte */
  5253.     cnt -= 4;
  5254.  
  5255.     ckhexdump("k5_auth_is data",data,cnt);
  5256.     debug(F111,"k5_auth_is","how",how);
  5257.  
  5258.     if (cnt-- < 1) {
  5259.         auth_finished(AUTH_REJECT);
  5260.         return AUTH_FAILURE;
  5261.     }
  5262.     switch (*data++) {
  5263.     case KRB_AUTH:
  5264.         k5_auth.data = (char *)data;
  5265.         k5_auth.length = cnt;
  5266.  
  5267.         debug(F110,"k5_auth_is","KRB_AUTH",0);
  5268.         debug(F111,"k5_auth_is","auth_context",auth_context);
  5269.  
  5270.         if (!r && !auth_context) {
  5271.             r = krb5_auth_con_init(k5_context, &auth_context);
  5272.             debug(F111,"k5_auth_is","krb5_auth_con_init",r);
  5273.         }
  5274.  
  5275. #ifdef HEIMDAL
  5276.         if (!r)
  5277.             r = krb5_auth_con_setaddrs_from_fd(k5_context,
  5278.                            auth_context,
  5279.                            &ttyfd);
  5280.         if (!r)
  5281.             r = krb5_sock_to_principal(k5_context,
  5282.                        0,
  5283.                        "host",
  5284.                                        KRB5_NT_SRV_HST,
  5285.                        &server);
  5286.         if (!r)
  5287. #else /* HEIMDAL */
  5288.         if (!r) {
  5289.             krb5_rcache rcache = NULL;
  5290.  
  5291.             r = krb5_auth_con_getrcache(k5_context, auth_context,
  5292.                                          &rcache);
  5293.             debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
  5294.  
  5295.             if (!r && !rcache) {
  5296.                 /* Do not resolve server's principal name, we will check */
  5297.                 /* for validity after the krb5_rd_req() call.            */
  5298.                 r = krb5_sname_to_principal(k5_context, 0, 0,
  5299.                                              KRB5_NT_SRV_HST, &server);
  5300.                 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
  5301.  
  5302.                 if (!r) {
  5303.                     r = krb5_get_server_rcache(k5_context,
  5304.                         krb5_princ_component(k5_context, server, 0),
  5305.                                                 &rcache);
  5306.                     debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
  5307.                     krb5_free_principal(k5_context, server);
  5308.                 }
  5309.             }
  5310.             if (!r) {
  5311.                 r = krb5_auth_con_setrcache(k5_context,
  5312.                                              auth_context, rcache);
  5313.                 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
  5314.             }
  5315.         }
  5316.         if (!r && k5_keytab) {
  5317.             r = krb5_kt_resolve(k5_context,
  5318.                                  k5_keytab, &keytabid);
  5319.             debug(F111,"k5_auth_is","krb5_kt_resolve",r);
  5320.         }
  5321. #endif /* HEIMDAL */
  5322.         if (!r) {
  5323.             r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
  5324. #ifdef HEIMDAL
  5325.                              server, NULL, NULL,
  5326. #else /* HEIMDAL */
  5327.                              NULL, keytabid, NULL,
  5328. #endif /* HEIMDAL */
  5329.                              &k5_ticket);
  5330.             debug(F111,"k5_auth_is","krb5_rd_req",r);
  5331.         }
  5332.         if (r) {
  5333.             (void) ckstrncpy(errbuf, "krb5_rd_req failed: ",sizeof(errbuf));
  5334.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5335.             goto errout;
  5336.         }
  5337. #ifdef HEIMDAL
  5338.         krb5_free_principal(k5_context, server);
  5339.  
  5340.         {
  5341.             char type_check[26];
  5342.  
  5343.             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
  5344.             /* client and then server finished messages. */
  5345.  
  5346.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  5347.             type_check[1] = how;        /* not broken into parts */
  5348. #ifdef CK_SSL
  5349.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5350.                 ssl_get_client_finished(&type_check[2],12);
  5351.                 ssl_get_server_finished(&type_check[14],12);
  5352.                 ckhexdump("k5_auth_is type_check",type_check,26);
  5353.             }
  5354. #endif /* CK_SSL */
  5355.  
  5356.             r = krb5_verify_authenticator_checksum(k5_context,
  5357.                                                     auth_context,
  5358.                                                     type_check,
  5359. #ifdef CK_SSL
  5360.                 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  5361. #endif /* CK_SSL */
  5362.                                                     2);
  5363.         }
  5364. #else /* HEIMDAL */
  5365.         len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
  5366.         if (len < 256)
  5367.         {
  5368.             memcpy(princ,
  5369.                    krb5_princ_component(k5_context,k5_ticket->server,0)->data,
  5370.                    len);
  5371.             princ[len] = '\0';
  5372.         }
  5373.         if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
  5374.         {
  5375.             debug(F110,"k5_auth_is incorrect service name",princ,0);
  5376.             ckstrncpy(errbuf,"incorrect service name: ",sizeof(errbuf));
  5377.             ckstrncat(errbuf,krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5378.                      sizeof(errbuf));
  5379.             ckstrncat(errbuf," != ",sizeof(errbuf));
  5380.             ckstrncat(errbuf,princ,sizeof(errbuf));
  5381.             goto errout;
  5382.         }
  5383.  
  5384.         r = krb5_auth_con_getauthenticator(k5_context,
  5385.                                             auth_context,
  5386.                                             &authenticator);
  5387.         debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
  5388.         if (r) {
  5389.             (void) ckstrncpy(errbuf,
  5390.                              "krb5_auth_con_getauthenticator failed: ",
  5391.                              sizeof(errbuf)
  5392.                              );
  5393.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5394.             goto errout;
  5395.         }
  5396.  
  5397.         if (authenticator->checksum) {
  5398.             char type_check[26];
  5399.             krb5_checksum *cksum = authenticator->checksum;
  5400.             krb5_keyblock *key;
  5401.  
  5402.             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
  5403.             /* client and then server finished messages. */
  5404.  
  5405.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  5406.             type_check[1] = how;        /* not broken into parts */
  5407. #ifdef CK_SSL
  5408.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5409.                 ssl_get_client_finished(&type_check[2],12);
  5410.                 ssl_get_server_finished(&type_check[14],12);
  5411.                 ckhexdump("k5_auth_is type_check",type_check,26);
  5412.             }
  5413. #endif /* CK_SSL */
  5414.  
  5415.             r = krb5_auth_con_getkey(k5_context, auth_context,
  5416.                                       &key);
  5417.             debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
  5418.             if (r) {
  5419.                 (void) ckstrncpy(errbuf, "krb5_auth_con_getkey failed: ",
  5420.                                   sizeof(errbuf));
  5421.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5422.                 goto errout;
  5423.             }
  5424.  
  5425.             r = krb5_verify_checksum(k5_context,
  5426.                                       cksum->checksum_type,
  5427.                                       cksum,
  5428.                                       &type_check,
  5429.                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  5430.                                       2,
  5431.                                       key->contents,
  5432.                                       key->length
  5433.                                       );
  5434.             debug(F111,"k5_auth_is","krb5_verify_checksum",r);
  5435.             if (r) {
  5436.                 (void) ckstrncpy(errbuf,
  5437.                                  "checksum verification failed: ",
  5438.                                  sizeof(errbuf)
  5439.                                  );
  5440.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5441.                 goto errout;
  5442.             }
  5443.             krb5_free_keyblock(k5_context, key);
  5444.         } else {
  5445.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
  5446.                 (void) strcpy(errbuf,
  5447.                                "authenticator is missing required checksum");
  5448.                 goto errout;
  5449.             }
  5450.         }
  5451.  
  5452.         krb5_free_authenticator(k5_context, authenticator);
  5453. #endif /* HEIMDAL */
  5454.  
  5455. #ifdef TLS_VERIFY
  5456.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5457.             krb5_data in, msg;
  5458.             char tls_verify[24];
  5459.             krb5_replay_data repdata;
  5460.  
  5461.             ssl_get_server_finished(&tls_verify[0],12);
  5462.             ssl_get_client_finished(&tls_verify[12],12);
  5463.  
  5464.             in.data = tls_verify;
  5465.             in.length = 24;
  5466.  
  5467.             krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  5468.                                    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
  5469.             if (r = krb5_mk_safe(k5_context,auth_context,&in,&msg,&repdata)) {
  5470.                 com_err("", r, "encoding tls verifier");
  5471.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5472.                 goto errout;
  5473.             }
  5474.             SendK5AuthSB(KRB5_TLS_VERIFY, msg.data, msg.length);
  5475.             krb5_free_data_contents(k5_context,&msg);
  5476.         }
  5477. #endif /* CK_SSL */
  5478.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  5479.             /* do ap_rep stuff here */
  5480.             if ((r = krb5_mk_rep(k5_context,
  5481. #ifdef HEIMDAL
  5482.                                   &auth_context,
  5483. #else /* HEIMDAL */
  5484.                                   auth_context,
  5485. #endif /* HEIMDAL */
  5486.                                   &outbuf))) {
  5487.                 debug(F111,"k5_auth_is","krb5_mk_rep",r);
  5488.                 (void) ckstrncpy(errbuf, "Make reply failed: ",sizeof(errbuf));
  5489.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5490.                 goto errout;
  5491.             }
  5492.             debug(F111,"k5_auth_is","krb5_mk_rep",r);
  5493.  
  5494.             SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
  5495.             mutual_complete = 1;
  5496.         }
  5497.  
  5498. #ifdef HEIMDAL
  5499.         {
  5500.             char * name = NULL;
  5501.             if (krb5_unparse_name(k5_context, k5_ticket->client,
  5502.                                    &name))
  5503.             {
  5504.                 szUserNameAuthenticated[0] = '\0';
  5505.             } else {
  5506.                 ckstrncpy(szUserNameAuthenticated,UIDBUFLEN,name);
  5507.                 free(name);
  5508.             }
  5509.         }
  5510. #else /* HEIMDAL */
  5511.         if ( krb5_aname_to_localname(k5_context,
  5512.                                       k5_ticket->enc_part2->client,
  5513.                                       UIDBUFLEN,szUserNameAuthenticated) )
  5514.             szUserNameAuthenticated[0] = '\0';
  5515. #endif /* HEIMDAL */
  5516.  
  5517.         SendK5AuthSB(KRB_ACCEPT, szUserNameAuthenticated,
  5518.                       szUserNameAuthenticated[0] ? -1 : 0);
  5519.         accept_complete = 1;
  5520.         ckmakmsg(strTmp,sizeof(strTmp),
  5521.                  "Kerberos5 identifies him as ``",
  5522.                  szUserNameAuthenticated,"''",NULL);
  5523.         printf("%s\r\n",strTmp);
  5524.  
  5525.         if (szUserNameRequested[0] &&
  5526.             krb5_kuserok(k5_context,
  5527. #ifdef HEIMDAL
  5528.                           k5_ticket->client,
  5529. #else /* HEIMDAL */
  5530.                           k5_ticket->enc_part2->client,
  5531. #endif /* HEIMDAL */
  5532.                           szUserNameRequested))
  5533.             auth_finished(AUTH_VALID);
  5534.         else
  5535.             auth_finished(AUTH_USER);
  5536.  
  5537.         krb5_auth_con_getremotesubkey(k5_context, auth_context,
  5538.                                        &newkey);
  5539.         if (k5_session_key) {
  5540.             krb5_free_keyblock(k5_context, k5_session_key);
  5541.             k5_session_key = 0;
  5542.         }
  5543.         if (newkey) {
  5544.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  5545.             krb5_free_keyblock(k5_context, newkey);
  5546.         } else {
  5547.             krb5_copy_keyblock(k5_context,
  5548. #ifdef HEIMDAL
  5549.                                 &k5_ticket->ticket.key,
  5550. #else /* HEIMDAL */
  5551.                                 k5_ticket->enc_part2->session,
  5552. #endif /* HEIMDAL */
  5553.                                 &k5_session_key);
  5554.         }
  5555.  
  5556. #ifdef CK_ENCRYPTION
  5557. #ifdef HEIMDAL
  5558.         skey.type = k5_session_key->keyvalue.length == 8 ? SK_DES : SK_GENERIC;
  5559.         skey.length = k5_session_key->keyvalue.length;
  5560.         skey.data = k5_session_key->keyvalue.data;
  5561. #else /* HEIMDAL */
  5562.         skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
  5563.         skey.length = k5_session_key->length;
  5564.         skey.data = k5_session_key->contents;
  5565. #endif /* HEIMDAL */
  5566.         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  5567. #endif /* CK_ENCRYPTION */
  5568.         debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
  5569.         krb5_errno = r;
  5570.         if ( krb5_errno )
  5571.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5572.         else
  5573.             makestr(&krb5_errmsg,strTmp);
  5574.         return AUTH_SUCCESS;
  5575.  
  5576. #ifdef FORWARD
  5577.     case KRB5_FORWARD:
  5578.         if ( !forward_flag ) {
  5579.             SendK5AuthSB(KRB5_FORWARD_REJECT,
  5580.                           "forwarded credentials are being refused.",
  5581.                           -1);
  5582.             return(AUTH_SUCCESS);
  5583.         }
  5584.  
  5585.         inbuf.length = cnt;
  5586.         inbuf.data = (char *)data;
  5587.         if (
  5588. #ifndef HEIMDAL
  5589.             (!krb5_d_no_addresses &&
  5590.             (r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
  5591.                               KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) ||
  5592. #endif /* HEIMDAL */
  5593.             (r = rd_and_store_for_creds(k5_context, auth_context,&inbuf,
  5594. #ifdef HEIMDAL
  5595.                                          k5_ticket->client
  5596. #else /* HEIMDAL */
  5597.                                          k5_ticket->enc_part2->client
  5598. #endif /* HEIMDAL */
  5599.                                          ))) {
  5600.             (void) ckstrncpy(errbuf, "Read forwarded creds failed: ",
  5601.                               sizeof(errbuf));
  5602.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5603.             SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
  5604.             printf("Could not read forwarded credentials\r\n");
  5605.             krb5_errno = r;
  5606.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5607.         }
  5608.         else {
  5609.             SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
  5610.             ckstrncpy(strTmp,"Forwarded credentials obtained",sizeof(strTmp));
  5611.             printf("%s\r\n",strTmp);
  5612.             krb5_errno = 0;
  5613.             makestr(&krb5_errmsg,strTmp);
  5614.         }
  5615.         /* A failure to accept forwarded credentials is not an */
  5616.         /* authentication failure.                             */
  5617.         return AUTH_SUCCESS;
  5618. #endif  /* FORWARD */
  5619.     default:
  5620.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  5621.         SendK5AuthSB(KRB_REJECT, 0, 0);
  5622.         break;
  5623.     }
  5624.     auth_finished(AUTH_REJECT);
  5625.     return AUTH_FAILURE;
  5626.  
  5627.   errout:
  5628.     SendK5AuthSB(KRB_REJECT, errbuf, -1);
  5629.     krb5_errno = r;
  5630.     makestr(&krb5_errmsg,errbuf);
  5631.     printf("%s\r\n", errbuf);
  5632.     if (auth_context) {
  5633.         krb5_auth_con_free(k5_context, auth_context);
  5634.         auth_context = 0;
  5635.     }
  5636.     auth_finished(AUTH_REJECT);
  5637.     return AUTH_FAILURE;
  5638. }
  5639.  
  5640. #ifdef FORWARD
  5641. int
  5642. #ifdef CK_ANSIC
  5643. kerberos5_forward(void)
  5644. #else
  5645. kerberos5_forward()
  5646. #endif
  5647. {
  5648.     krb5_error_code r;
  5649.     krb5_ccache ccache=NULL;
  5650.     krb5_principal client = 0;
  5651.     krb5_principal server = 0;
  5652.     krb5_data forw_creds;
  5653. #ifdef HEIMDAL
  5654.     krb5_creds      creds;
  5655. #endif /* HEIMDAL */
  5656.  
  5657.     forw_creds.data = 0;
  5658.  
  5659.     r = k5_get_ccache(k5_context,&ccache,NULL);
  5660.     if ( r ) {
  5661.         com_err(NULL, r, "Kerberos V5: could not get default ccache");
  5662.         krb5_errno = r;
  5663.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5664.         return(AUTH_FAILURE);
  5665.     }
  5666.  
  5667.     if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
  5668.         com_err(NULL, r, "Kerberos V5: could not get default principal");
  5669.         goto cleanup;
  5670.     }
  5671.  
  5672. #ifdef HEIMDAL
  5673.     memset(&creds, 0, sizeof(creds));
  5674.     creds.client = client;
  5675.  
  5676.     if (r = krb5_build_principal(k5_context,
  5677.                              &creds.server,
  5678.                              strlen(client->realm),
  5679.                               client->realm,
  5680.                               "krbtgt",
  5681.                               client->realm,
  5682.                                   NULL)) {
  5683.         com_err(NULL, r, "Kerberos V5: could not get principal");
  5684.         goto cleanup;
  5685.     }
  5686.  
  5687.     creds.times.endtime = 0;
  5688.  
  5689.     if (r = krb5_get_forwarded_creds(k5_context,
  5690.                                       auth_context,
  5691.                                       ccache,
  5692.                                       0,
  5693.                                       szHostName,
  5694.                                       &creds,
  5695.                                       &forw_creds)) {
  5696.         com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
  5697.         goto cleanup;
  5698.     }
  5699. #else /* HEIMDAL */
  5700.     /* we should not need to make this call since we are storing the */
  5701.     /* server's principal in fwd_server from our call to             */
  5702.     /* krb5_sname_to_principal() in k5_auth_send()                   */
  5703.     if (fwd_server == NULL) {
  5704.         if ((r = krb5_sname_to_principal(k5_context, szHostName,
  5705.                                  krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5706.                                           KRB5_NT_SRV_HST, &server))) {
  5707.             com_err(NULL, r, "Kerberos V5: could not make server principal");
  5708.             goto cleanup;
  5709.         }
  5710.     }
  5711.  
  5712.     if (!krb5_d_no_addresses &&
  5713.         (r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
  5714.                              KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
  5715.     {
  5716.         com_err(NULL, r, "Kerberos V5: could not gen local full address");
  5717.         goto cleanup;
  5718.     }
  5719.  
  5720.     if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client,
  5721.                                 fwd_server ? fwd_server : server,
  5722.                                 ccache, forwardable_flag, &forw_creds)) {
  5723.         com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
  5724.         goto cleanup;
  5725.     }
  5726. #endif /* HEIMDAL */
  5727.  
  5728.     /* Send forwarded credentials */
  5729.     if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
  5730.         printf("Kerberos V5 forwarding error!\r\n%s\r\n",
  5731.                     "Not enough room for authentication data");
  5732.     }
  5733.  
  5734. cleanup:
  5735.     if (client)
  5736.         krb5_free_principal(k5_context, client);
  5737.     if (server)
  5738.         krb5_free_principal(k5_context, server);
  5739. #ifdef HEIMDAL
  5740.     krb5_data_free(&forw_creds);
  5741. #else /* HEIMDAL */
  5742.     krb5_free_data_contents(k5_context,&forw_creds);
  5743. #endif /* HEIMDAL */
  5744.     krb5_cc_close(k5_context, ccache);
  5745.  
  5746.     krb5_errno = r;
  5747.     makestr(&krb5_errmsg,krb5_errno?error_message(krb5_errno):"OK");
  5748.     return(r?AUTH_FAILURE:AUTH_SUCCESS);
  5749. }
  5750. #endif /* FORWARD */
  5751. #else /* KRB5 */
  5752. int
  5753. ck_krb5_autoget_TGT(char * dummy)
  5754. {
  5755.     return(0);
  5756. }
  5757. #ifdef CK_KERBEROS
  5758. int
  5759. #ifdef CK_ANSIC
  5760. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
  5761.                  struct krb4_init_data * k4_init)
  5762. #else
  5763. ck_krb5_initTGT(op,init,k4_init)
  5764.     krb_op_data * op; struct krb5_init_data * init;
  5765.     struct krb4_init_data * k4_init;
  5766. #endif /* CK_ANSIC*/
  5767. {
  5768.     return(-1);
  5769. }
  5770.  
  5771. int
  5772. #ifdef CK_ANSIC
  5773. ck_krb5_destroy(struct krb_op_data * op)
  5774. #else
  5775. ck_krb5_destroy(op) struct krb_op_data * op;
  5776. #endif
  5777. {
  5778.     return(-1);
  5779. }
  5780.  
  5781. int
  5782. #ifdef CK_ANSIC
  5783. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  5784. #else
  5785. ck_krb5_list_creds(op,lc)
  5786.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  5787. #endif
  5788. {
  5789.     return(-1);
  5790. }
  5791. #else /* CK_KERBEROS */
  5792. int
  5793. #ifdef CK_ANSIC
  5794. ck_krb5_initTGT(void * op, void * init, void * k4_init )
  5795. #else
  5796. ck_krb5_initTGT(op,init,k4_init)
  5797.     void * op; void * init; void * k4_init;
  5798. #endif /* CK_ANSIC*/
  5799. {
  5800.     return(-1);
  5801. }
  5802.  
  5803. int
  5804. #ifdef CK_ANSIC
  5805. ck_krb5_destroy(void * op)
  5806. #else
  5807. ck_krb5_destroy(op) void * op;
  5808. #endif
  5809. {
  5810.     return(-1);
  5811. }
  5812.  
  5813. int
  5814. #ifdef CK_ANSIC
  5815. ck_krb5_list_creds(void * op, void * lc)
  5816. #else
  5817. ck_krb5_list_creds(op,lc)
  5818.     void * op; void * lc;
  5819. #endif
  5820. {
  5821.     return(-1);
  5822. }
  5823. #endif /* CK_KERBEROS */
  5824. #endif /* KRB5 */
  5825.  
  5826. #ifdef GSSAPI_KRB5
  5827. /*
  5828.  *
  5829.  * gssk5_auth_send - gets authentication bits we need to send to KDC.
  5830.  *
  5831.  * Result is left in k5_auth
  5832.  *
  5833.  * Returns: 0 on failure, 1 on success
  5834.  *
  5835.  */
  5836.  
  5837. static int
  5838. #ifdef CK_ANSIC
  5839. gssk5_auth_send(int how, int encrypt, int forward)
  5840. #else
  5841. gssk5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
  5842. #endif
  5843. {
  5844.     OM_uint32 maj_stat, min_stat;
  5845. #ifdef KRB5
  5846.     char * realm = NULL;
  5847.     char tgt[256];
  5848. #endif /* KRB5 */
  5849.  
  5850.     gss_chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */
  5851.     gss_chan.initiator_address.length = 4;
  5852.     gss_chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
  5853.     gss_chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
  5854.     gss_chan.acceptor_address.length = 4;
  5855.     gss_chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
  5856.     gss_chan.application_data.length = 0;
  5857.     gss_chan.application_data.value = 0;
  5858.  
  5859. #ifdef KRB5
  5860.     realm = ck_krb5_realmofhost(ftp_host);
  5861.     if (realm) {
  5862.         ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  5863.         debug(F110,"ftp_auth(GSSAPI) TGT",tgt,0);
  5864.         if ( krb5_autoget &&
  5865.              !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  5866.                 (ck_krb5_is_tgt_valid() > 0)) )
  5867.             ck_krb5_autoget_TGT(realm);
  5868.     }
  5869. #endif /* KRB5 */
  5870.  
  5871.     /* Blob from gss-client */
  5872.     /* host@hostname */
  5873.     /* the V5 GSSAPI binding canonicalizes this for us... */
  5874.     ckmakmsg(gss_stbuf,GSS_BUFSIZ,
  5875.              krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5876.              "@",
  5877.              szHostName,
  5878.               NULL
  5879.               );
  5880.     fprintf(stderr, "Authenticating to <%s>...\n", gss_stbuf);
  5881.     gss_send_tok.value = gss_stbuf;
  5882.     gss_send_tok.length = strlen(gss_stbuf);
  5883.     maj_stat = gss_import_name(&min_stat, &gss_send_tok,
  5884.                                 gss_nt_service_name,
  5885.                                 &gss_target_name
  5886.                                 );
  5887.     if (maj_stat != GSS_S_COMPLETE) {
  5888.         user_gss_error(maj_stat, min_stat, "parsing name");
  5889.         secure_error("name parsed <%s>\n", gss_stbuf);
  5890.         return(0);
  5891.     }
  5892.     token_ptr = GSS_C_NO_BUFFER;
  5893.     gcontext = GSS_C_NO_CONTEXT; /* structure copy */
  5894.  
  5895.     fprintf(stderr, "calling gss_init_sec_context\n");
  5896.     maj_stat =
  5897.         gss_init_sec_context(&min_stat,
  5898.                               GSS_C_NO_CREDENTIAL,
  5899.                               &gcontext,
  5900.                               gss_target_name,
  5901.                               gss_mech_krb5,
  5902.                               GSS_C_MUTUAL_FLAG |
  5903.                               GSS_C_REPLAY_FLAG |
  5904.                               ((forward && forward_flag) ?
  5905.                                 GSS_C_DELEG_FLAG : 0),
  5906.                               0,
  5907.                               (krb5_d_no_addresses ? /* channel bindings */
  5908.                                 GSS_C_NO_CHANNEL_BINDINGS :
  5909.                                 &gss_chan),
  5910.                               gss_token_ptr,
  5911.                               NULL,     /* ignore mech type */
  5912.                               &gss_send_tok,
  5913.                               NULL,     /* ignore ret_flags */
  5914.                               NULL
  5915.                               );        /* ignore time_rec */
  5916.  
  5917.  
  5918.         if (maj_stat != GSS_S_COMPLETE &&
  5919.              maj_stat != GSS_S_CONTINUE_NEEDED) {
  5920.             user_gss_error(maj_stat,
  5921.                             min_stat,
  5922.                             "initializing context"
  5923.                             );
  5924.             gss_release_name(&min_stat, &gss_target_name);
  5925.             return(0);
  5926.         }
  5927.         return(1);
  5928. }
  5929.  
  5930. /*
  5931.  * gssk5_auth_reply -- checks the reply for mutual authentication.
  5932.  */
  5933. static int
  5934. #ifdef CK_ANSIC
  5935. gssk5_auth_reply(int how, unsigned char *data, int cnt)
  5936. #else
  5937. gssk5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  5938. #endif
  5939. {
  5940.     data += 4;                                  /* Point to status byte */
  5941.     cnt -=5;
  5942.  
  5943.     switch (*data++) {
  5944.     case GSS_REJECT:
  5945.         if (cnt > 0) {
  5946.             char *s;
  5947.             int len;
  5948.             ckstrncpy(strTmp,"GSSAPI refuses authentication because\r\n",
  5949.                       sizeof(strTmp));
  5950.             len = strlen(strTmp);
  5951.             if ( len + cnt < sizeof(strTmp) ) {
  5952.                 s = strTmp + strlen(strTmp);
  5953.                 memcpy(s, data, cnt);           /* safe */
  5954.                 s[cnt] = 0;
  5955.             }
  5956.         } else
  5957.             ckstrncpy(strTmp,"GSSAPI refuses authentication",
  5958.                       sizeof(strTmp));
  5959.         printf("GSSAPI authentication failed!\r\n%s\r\n",strTmp);
  5960.         auth_finished(AUTH_REJECT);
  5961.         return AUTH_FAILURE;
  5962.  
  5963.     case GSS_ACCEPT:
  5964.         if ( cnt > 0 ) {
  5965.             char *s;
  5966.             int len;
  5967.             ckstrncpy(strTmp,"GSSAPI accepts you as ",sizeof(strTmp));
  5968.             len = strlen(strTmp);
  5969.             if ( len + cnt < sizeof(strTmp) ) {
  5970.                 s = strTmp + strlen(strTmp);
  5971.                 memcpy(s,data,cnt);
  5972.                 s[cnt] = 0;
  5973.             }
  5974.         }
  5975.         accept_complete = 1;
  5976.         printf("%s\r\n",strTmp);
  5977.         auth_finished(AUTH_USER);
  5978.         return AUTH_SUCCESS;
  5979.  
  5980.     case GSS_RESPONSE:
  5981.         gss_token_ptr = &gss_recv_tok;
  5982.         gss_recv_tok.value = data;
  5983.         gss_recv_tok.length = cnt;
  5984.  
  5985.         maj_stat =
  5986.             gss_init_sec_context(&min_stat,
  5987.                                   GSS_C_NO_CREDENTIAL,
  5988.                                   &gcontext,
  5989.                                   gss_target_name,
  5990.                                   gss_krb5_mech,
  5991.                                   GSS_C_MUTUAL_FLAG |
  5992.                                   GSS_C_REPLAY_FLAG |
  5993.                                   (forward_flag ?
  5994.                                     GSS_C_DELEG_FLAG : 0),
  5995.                                   0,
  5996.                                   (krb5_d_no_addresses ? /* channel bindings */
  5997.                                     GSS_C_NO_CHANNEL_BINDINGS :
  5998.                                     &gss_chan),
  5999.                                   gss_token_ptr,
  6000.                                   NULL, /* ignore mech type */
  6001.                                   &gss_send_tok,
  6002.                                   NULL, /* ignore ret_flags */
  6003.                                   NULL
  6004.                                   );    /* ignore time_rec */
  6005.  
  6006.         if ( maj_stat == GSS_S_COMPLETE )
  6007.         {
  6008.  
  6009.         } else if ( maj_stat == CSS_S_CONTINUE_NEEDED ) {
  6010.         } else {
  6011.         }
  6012.  
  6013.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  6014.                   sizeof(strTmp));
  6015.         printf("%s\r\n",strTmp);
  6016.         auth_finished(AUTH_USER);
  6017.         return AUTH_SUCCESS;
  6018.  
  6019.     default:
  6020.         auth_finished(AUTH_REJECT);
  6021.         return AUTH_FAILURE;                        /* Unknown reply type */
  6022.     }
  6023. }
  6024.  
  6025. /*
  6026.  *
  6027.  * gssk5_auth_is.
  6028.  *
  6029.  */
  6030.  
  6031. static int
  6032. #ifdef CK_ANSIC
  6033. k5_auth_is(int how, unsigned char *data, int cnt)
  6034. #else
  6035. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  6036. #endif
  6037. {
  6038.     int replied = 0;
  6039.     gss_cred_id_t server_creds, deleg_creds;
  6040.     gss_name_t client;
  6041.     int ret_flags;
  6042.     gss_buffer_desc name_buf;
  6043.     gss_name_t server_name;
  6044.     OM_uint32 acquire_maj,
  6045.       acquire_min,
  6046.       accept_maj,
  6047.       accept_min,
  6048.       stat_maj,
  6049.       stat_min;
  6050.     gss_OID mechid;
  6051.     gss_buffer_desc tok, out_tok;
  6052.     char gbuf[GSS_BUFSIZ];
  6053.     u_char gout_buf[GSS_BUFSIZ];
  6054.     char localname[MAXHOSTNAMELEN];
  6055.     char service_name[MAXHOSTNAMELEN+10];
  6056.     char **service;
  6057.     struct hostent *hp;
  6058.  
  6059.     data += 4;                                  /* Point to status byte */
  6060.     cnt -= 4;
  6061.  
  6062.     ckhexdump("gssk5_auth_is data",data,cnt);
  6063.     debug(F111,"gssk5_auth_is","how",how);
  6064.  
  6065.     if (cnt-- < 1) {
  6066.         auth_finished(AUTH_REJECT);
  6067.         return AUTH_FAILURE;
  6068.     }
  6069.     switch (*data++) {
  6070.     case GSS_AUTH:
  6071.         gss_chan.initiator_addrtype = GSS_C_AF_INET;
  6072.         gss_chan.initiator_address.length = 4;
  6073.         gss_chan.initiator_address.value = &his_addr.sin_addr.s_addr;
  6074.         gss_chan.acceptor_addrtype = GSS_C_AF_INET;
  6075.         gss_chan.acceptor_address.length = 4;
  6076.         gss_chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
  6077.         gss_chan.application_data.length = 0;
  6078.         gss_chan.application_data.value = 0;
  6079.  
  6080.         tok.value = data;
  6081.         tok.length = cnt;
  6082.  
  6083.         if (gethostname(localname, MAXHOSTNAMELEN)) {
  6084.             auth_finished(AUTH_REJECT);
  6085.             return AUTH_FAILURE;
  6086.         }
  6087.         if (!(hp = gethostbyname(localname))) {
  6088.             auth_finished(AUTH_REJECT);
  6089.             return AUTH_FAILURE;
  6090.         }
  6091. #ifdef HADDRLIST
  6092.         hp = ck_copyhostent(hp);
  6093. #endif /* HADDRLIST */
  6094.         strncpy(localname, hp->h_name, sizeof(localname) - 1);
  6095.         localname[sizeof(localname) - 1] = '\0';
  6096.  
  6097.         sprintf(service_name, "%s@%s", *service, localname);
  6098.         name_buf.value = service_name;
  6099.         name_buf.length = strlen(name_buf.value) + 1;
  6100.         stat_maj = gss_import_name(&stat_min, &name_buf,
  6101.                                     gss_nt_service_name,
  6102.                                     &server_name);
  6103.         if (stat_maj != GSS_S_COMPLETE) {
  6104.             auth_finished(AUTH_REJECT);
  6105.             return AUTH_FAILURE;
  6106.         }
  6107.  
  6108.         acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
  6109.                                         GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
  6110.                                         &server_creds, NULL, NULL);
  6111.         (void) gss_release_name(&stat_min, &server_name);
  6112.  
  6113.         if (acquire_maj != GSS_S_COMPLETE) {
  6114.             reply_gss_error(535, accept_maj, accept_min,
  6115.                                  "accepting context");
  6116.             syslog(LOG_ERR, "failed accepting context");
  6117.             (void) gss_release_cred(&stat_min, &server_creds);
  6118.             if (ret_flags & GSS_C_DELEG_FLAG)
  6119.                 (void) gss_release_cred(&stat_min,
  6120.                                          &deleg_creds);
  6121.             return 0;
  6122.         }
  6123.  
  6124.         gcontext = GSS_C_NO_CONTEXT;
  6125.         accept_maj = gss_accept_sec_context(&accept_min,
  6126.                                             &gcontext, /* context_handle */
  6127.                                             /* verifier_cred_handle */
  6128.                                             server_creds,
  6129.                                             &tok, /* input_token */
  6130.                         (krb5_d_no_addresses ?
  6131.                          /* channel bindings */
  6132.                                                GSS_C_NO_CHANNEL_BINDINGS :
  6133.                                                &gss_chan),
  6134.                                              &client, /* src_name */
  6135.                                             &mechid, /* mech_type */
  6136.                                             &out_tok, /* output_token */
  6137.                                             &ret_flags,
  6138.                                             NULL,       /* ignore time_rec */
  6139.                                             /* forwarded credentials */
  6140.                                             &deleg_creds
  6141.                                             );
  6142.  
  6143.         if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
  6144.             reply_gss_error(535, accept_maj, accept_min,
  6145.                              "accepting context");
  6146.             syslog(LOG_ERR, "failed accepting context");
  6147.             (void) gss_release_cred(&stat_min, &server_creds);
  6148.             if (ret_flags & GSS_C_DELEG_FLAG)
  6149.                 (void) gss_release_cred(&stat_min,
  6150.                                          &deleg_creds);
  6151.             return 0;
  6152.         }
  6153.  
  6154.         if (out_tok.length) {
  6155.             if (kerror = radix_encode(out_tok.value,gbuf,&out_tok.length, 0)) {
  6156.                 secure_error("Couldn't encode ADAT reply (%s)",
  6157.                              radix_error(kerror));
  6158.                 syslog(LOG_ERR, "couldn't encode ADAT reply");
  6159.                 (void) gss_release_cred(&stat_min, &server_creds);
  6160.                 if (ret_flags & GSS_C_DELEG_FLAG)
  6161.                         (void) gss_release_cred(&stat_min,
  6162.                                                 &deleg_creds);
  6163.                 return(0);
  6164.             }
  6165.             if (stat_maj == GSS_S_COMPLETE) {
  6166.                 reply(235, "ADAT=%s", gbuf);
  6167.                 replied = 1;
  6168.             } else {
  6169.                 /* If the server accepts the security data, and
  6170.                    requires additional data, it should respond
  6171.                    with reply code 335. */
  6172.                 reply(335, "ADAT=%s", gbuf);
  6173.             }
  6174.             (void) gss_release_buffer(&stat_min, &out_tok);
  6175.         }
  6176.  
  6177.         if (stat_maj == GSS_S_COMPLETE) {
  6178.             /* GSSAPI authentication succeeded */
  6179.             stat_maj = gss_display_name(&stat_min, client,
  6180.                                          &client_name, &mechid);
  6181.             if (stat_maj != GSS_S_COMPLETE) {
  6182.                 /* "If the server rejects the security data (if
  6183.                    a checksum fails, for instance), it should
  6184.                    respond with reply code 535." */
  6185.                 reply_gss_error(535, stat_maj, stat_min,
  6186.                                 "extracting GSSAPI identity name");
  6187.                 syslog(LOG_ERR, "gssapi error extracting identity");
  6188.                 (void) gss_release_cred(&stat_min, &server_creds);
  6189.                 if (ret_flags & GSS_C_DELEG_FLAG)
  6190.                         (void) gss_release_cred(&stat_min,
  6191.                                                 &deleg_creds);
  6192.                 return 0;
  6193.             }
  6194.             auth_type = temp_auth_type;
  6195.             temp_auth_type = NULL;
  6196.  
  6197.             (void) gss_release_cred(&stat_min, &server_creds);
  6198.             if (ret_flags & GSS_C_DELEG_FLAG) {
  6199.                 if (want_creds)
  6200.                     ftpd_gss_convert_creds(client_name.value,
  6201.                                             deleg_creds);
  6202.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6203.             }
  6204.  
  6205.             /* If the server accepts the security data, but does
  6206.                not require any additional data (i.e., the security
  6207.                data exchange has completed successfully), it must
  6208.                respond with reply code 235. */
  6209.             if (!replied)
  6210.             {
  6211.                 if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
  6212.                   reply(235,
  6213.  "GSSAPI Authentication succeeded, but could not accept forwarded credentials"
  6214.                         );
  6215.                 else
  6216.                   reply(235, "GSSAPI Authentication succeeded");
  6217.             }
  6218.             return(1);
  6219.         } else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
  6220.             /* If the server accepts the security data, and
  6221.             requires additional data, it should respond with
  6222.             reply code 335. */
  6223.             reply(335, "more data needed");
  6224.             (void) gss_release_cred(&stat_min, &server_creds);
  6225.             if (ret_flags & GSS_C_DELEG_FLAG)
  6226.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6227.             return(0);
  6228.         } else {
  6229.             /* "If the server rejects the security data (if
  6230.             a checksum fails, for instance), it should
  6231.             respond with reply code 535." */
  6232.             reply_gss_error(535, stat_maj, stat_min,
  6233.                              "GSSAPI failed processing ADAT");
  6234.             syslog(LOG_ERR, "GSSAPI failed processing ADAT");
  6235.             (void) gss_release_cred(&stat_min, &server_creds);
  6236.             if (ret_flags & GSS_C_DELEG_FLAG)
  6237.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6238.             return(0);
  6239.         }
  6240.  
  6241.         debug(F100,"gssk5_auth_is AUTH_SUCCESS","",0);
  6242.         krb5_errno = r;
  6243.         if ( krb5_errno )
  6244.             makestr(&krb5_errmsg,error_message(krb5_errno));
  6245.         else
  6246.             makestr(&krb5_errmsg,strTmp);
  6247.         return AUTH_SUCCESS;
  6248.  
  6249.     default:
  6250.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  6251.         SendGSSK5AuthSB(GSS_REJECT, 0, 0);
  6252.         break;
  6253.     }
  6254.     auth_finished(AUTH_REJECT);
  6255.     return AUTH_FAILURE;
  6256. }
  6257. #endif /* GSSAPI_KRB5 */
  6258.  
  6259. #ifdef CK_SRP
  6260. /*
  6261.  * Copyright (c) 1997 Stanford University
  6262.  *
  6263.  * The use of this software for revenue-generating purposes may require a
  6264.  * license from the owners of the underlying intellectual property.
  6265.  * Specifically, the SRP-3 protocol may not be used for revenue-generating
  6266.  * purposes without a license.
  6267.  *
  6268.  * NOTE: Columbia University has a license.
  6269.  *
  6270.  * Within that constraint, permission to use, copy, modify, and distribute
  6271.  * this software and its documentation for any purpose is hereby granted
  6272.  * without fee, provided that the above copyright notices and this permission
  6273.  * notice appear in all copies of the software and related documentation.
  6274.  *
  6275.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  6276.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  6277.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  6278.  *
  6279.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  6280.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  6281.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
  6282.  * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
  6283.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  6284.  */
  6285.  
  6286. static void
  6287. srp_encode_length(data, num)
  6288.     unsigned char * data;
  6289.     int num;
  6290. {
  6291.     *data = (num >> 8) & 0xff;
  6292.     *++data = num & 0xff;
  6293. }
  6294.  
  6295. static int
  6296. srp_decode_length(data)
  6297.     unsigned char * data;
  6298. {
  6299.     return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
  6300. }
  6301.  
  6302. #ifdef PRE_SRP_1_7_3
  6303. static int
  6304. #ifdef CK_ANSIC
  6305. srp_reply(int how, unsigned char *data, int cnt)
  6306. #else
  6307. srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  6308. #endif
  6309. {
  6310.     struct t_num n;
  6311.     struct t_num g;
  6312.     struct t_num s;
  6313.     struct t_num B;
  6314.     struct t_num * A;
  6315.     char type_check[26];
  6316.     int pflag;
  6317.  
  6318. #ifdef CK_ENCRYPTION
  6319.     Session_Key skey;
  6320. #endif /* ENCRYPTION */
  6321.  
  6322.     char * str=NULL;
  6323.  
  6324.     data += 4;                          /* Point to status byte */
  6325.     cnt  -= 4;
  6326.  
  6327.     if(cnt-- < 1) {
  6328.         auth_finished(AUTH_REJECT);
  6329.         return AUTH_FAILURE;
  6330.     }
  6331.  
  6332.     switch(*data++) {
  6333.     case SRP_REJECT:
  6334.         ckmakmsg(strTmp,sizeof(strTmp),
  6335.                   "SRP refuses authentication for '",szUserName,
  6336.                   "'\r\n",NULL);
  6337.         if (cnt > 0) {
  6338.             int len = strlen(strTmp);
  6339.             if ( len + cnt < sizeof(strTmp) ) {
  6340.                 str = strTmp + strlen(strTmp);
  6341.                 memcpy(str,data,cnt);
  6342.                 str[cnt] = 0;
  6343.             }
  6344.         }
  6345.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  6346.         if (tc != NULL) {
  6347.             t_clientclose(tc);
  6348.             tc = NULL;
  6349.         }
  6350.         auth_finished(AUTH_REJECT);
  6351.         return AUTH_FAILURE;
  6352.  
  6353.     case SRP_ACCEPT:
  6354.         if(cnt < RESPONSE_LEN || !srp_waitresp ||
  6355.             tc == NULL
  6356.             ) {
  6357.             printf("SRP Protocol error\r\n");
  6358.             return(auth_resend(AUTHTYPE_SRP));
  6359.         }
  6360.         srp_waitresp = 0;
  6361.  
  6362.         if(t_clientverify(tc, data) == 0) {
  6363.             printf("SRP accepts you as %s\r\n",szUserName);
  6364. #ifdef CK_SSL
  6365.             if((ssl_active_flag || tls_active_flag) &&
  6366.                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6367.                 printf("TLS session parameters verified by SRP\r\n");
  6368.             } else
  6369. #endif /* CK_SSL */
  6370.  
  6371. #ifdef CK_ENCRYPTION
  6372.             {
  6373.                 skey.type = SK_GENERIC;
  6374.                 skey.length = SESSION_KEY_LEN;
  6375.                 skey.data = tc->session_key;
  6376.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  6377.             }
  6378. #endif /* ENCRYPTION */
  6379.             t_clientclose(tc);
  6380.             tc = NULL;
  6381.             accept_complete = 1;
  6382.             auth_finished(AUTH_VALID);
  6383.             return AUTH_SUCCESS;
  6384.         } else {
  6385.             printf("SRP server authentication failed!\r\n");
  6386.             t_clientclose(tc);
  6387.             tc = NULL;
  6388.             return(auth_resend(AUTHTYPE_SRP));
  6389.         }
  6390.         break;
  6391.  
  6392.     case SRP_PARAMS:
  6393.         if(!szUserName) {
  6394.             printf("No username available\r\n");
  6395.             return(auth_resend(AUTHTYPE_SRP));
  6396.         }
  6397.  
  6398.         n.len = srp_decode_length(data);
  6399.         data += 2;
  6400.         cnt -= 2;
  6401.         if(n.len > cnt) {
  6402.             printf("n too long\r\n");
  6403.             return(auth_resend(AUTHTYPE_SRP));
  6404.         }
  6405.         n.data = data;
  6406.         data += n.len;
  6407.         cnt -= n.len;
  6408.  
  6409.         g.len = srp_decode_length(data);
  6410.         data += 2;
  6411.         cnt -= 2;
  6412.         if(g.len > cnt) {
  6413.             printf("g too long\r\n");
  6414.             return(auth_resend(AUTHTYPE_SRP));
  6415.         }
  6416.         g.data = data;
  6417.         data += g.len;
  6418.         cnt -= g.len;
  6419.  
  6420.         s.len = srp_decode_length(data);
  6421.         data += 2;
  6422.         cnt -= 2;
  6423.         if(s.len > cnt) {
  6424.             printf("salt too long\r\n");
  6425.             return(auth_resend(AUTHTYPE_SRP));
  6426.         }
  6427.         s.data = data;
  6428.         data += s.len;
  6429.         cnt -= s.len;
  6430.  
  6431.         /* If the parameters provided by the server cannot be
  6432.          * validated the following function will fail.
  6433.          */
  6434.         tc = t_clientopen(szUserName, &n, &g, &s);
  6435.         if (tc == NULL) {
  6436.             printf("SRP parameter initialization error\r\n");
  6437.             return(auth_resend(AUTHTYPE_SRP));
  6438.         }
  6439.         A = t_clientgenexp(tc);
  6440.         if(A == NULL) {
  6441.             printf("SRP protocol error\r\n");
  6442.             return(auth_resend(AUTHTYPE_SRP));
  6443.         }
  6444.         SendSRPAuthSB(SRP_EXP, A->data, A->len);
  6445.  
  6446.         if ( pwbuf[0] && pwflg ) {
  6447.             printf("SRP using %d-bit modulus for '%s'\r\n",
  6448.                    8 * n.len,
  6449.                    szUserName
  6450.                    );
  6451.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  6452. #ifdef OS2
  6453.             if ( pwcrypt )
  6454.                 ck_encrypt((char *)srp_passwd);
  6455. #endif /* OS2 */
  6456.         } else {
  6457.             extern char * srppwprompt;
  6458.             char preface[128];
  6459.             int ok;
  6460.  
  6461.             if (srppwprompt && srppwprompt[0] &&
  6462.         (strlen(srppwprompt) + strlen(szUserName) - 2) <
  6463.         sizeof(preface)) {
  6464.                 sprintf(preface,srppwprompt,szUserName);
  6465.             } else {
  6466.                 ckmakxmsg( preface,sizeof(preface),
  6467.                           "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
  6468.                           szUserName, "'", NULL, NULL, NULL, NULL, NULL,
  6469.                           NULL, NULL);
  6470.             }
  6471.             ok = uq_txt( preface,"Password: ",2,NULL,
  6472.                          srp_passwd,sizeof(srp_passwd)-1,NULL,
  6473.              DEFAULT_UQ_TIMEOUT);
  6474.             if ( !ok )
  6475.                 srp_passwd[0] = '\0';
  6476.         }
  6477.  
  6478.         t_clientpasswd(tc, srp_passwd);
  6479.         memset(srp_passwd, 0, sizeof(srp_passwd));
  6480.         return AUTH_SUCCESS;
  6481.  
  6482.     case SRP_CHALLENGE:
  6483.         if(tc == NULL) {
  6484.             printf("SRP protocol error\r\n");
  6485.             return(auth_resend(AUTHTYPE_SRP));
  6486.         }
  6487.  
  6488. #ifndef PRE_SRP_1_4_5
  6489.         /*
  6490.          * The original SRP AUTH implementation did not protect against
  6491.          * tampering of the auth-type-pairs.  Therefore, when the
  6492.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6493.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6494.          * is set we also insert the SSL/TLS client and server finished
  6495.          * messages to ensure that there is no man in the middle attack
  6496.          * underway on the SSL/TLS connection.
  6497.          */
  6498.         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
  6499.             type_check[0] = AUTHTYPE_SRP;
  6500.             type_check[1] = how;
  6501. #ifdef CK_SSL
  6502.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6503.                 ssl_get_client_finished(&type_check[2],12);
  6504.                 ssl_get_server_finished(&type_check[14],12);
  6505.                 t_clientaddexdata(tc,type_check,26);
  6506.             } else
  6507. #endif /* CK_SSL */
  6508.                 t_clientaddexdata(tc,type_check,2);
  6509.         }
  6510. #endif /* PRE_SRP_1_4_5 */
  6511.  
  6512.         B.data = data;
  6513.         B.len = cnt;
  6514.         t_clientgetkey(tc, &B);
  6515.  
  6516.         SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
  6517.         srp_waitresp = 1;
  6518.         return AUTH_SUCCESS;
  6519.  
  6520.     default:
  6521.         return(auth_resend(AUTHTYPE_SRP));
  6522.     }
  6523.     return AUTH_FAILURE;
  6524. }
  6525.  
  6526. static int
  6527. #ifdef CK_ANSIC
  6528. srp_is(int how, unsigned char *data, int cnt)
  6529. #else
  6530. srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  6531. #endif
  6532. {
  6533.     char * pbuf = NULL;
  6534.     char * ptr;
  6535. #ifdef CK_ENCRYPTION
  6536.     Session_Key skey;
  6537. #endif
  6538.     struct t_num A;
  6539.     struct t_pw * tpw = NULL;
  6540.     struct t_conf * tconf = NULL;
  6541.     struct passwd * pass;
  6542.     static struct t_num * B = NULL;     /* Holder for B */
  6543. #ifdef CK_SSL
  6544.     char type_check[26];
  6545. #else
  6546.     char type_check[2];
  6547. #endif /* CK_SSL */
  6548.  
  6549.     if ((cnt -= 4) < 1) {
  6550.         auth_finished(AUTH_REJECT);
  6551.         return AUTH_FAILURE;
  6552.     }
  6553.  
  6554.     data += 4;
  6555.     cnt  -= 1;
  6556.     switch(*data++) {
  6557.     case SRP_AUTH:
  6558.         /* Send parameters back to client */
  6559.         if(ts != NULL) {
  6560.             t_serverclose(ts);
  6561.             ts = NULL;
  6562.         }
  6563.         if(!szUserNameRequested[0]) {
  6564.             if (1)
  6565.                 printf("No username available\r\n");
  6566.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  6567.             auth_finished(AUTH_REJECT);
  6568.             return(AUTH_FAILURE);
  6569.         }
  6570. #ifdef IKSD
  6571. #ifdef CK_LOGIN
  6572.         if (inserver && ckxanon &&
  6573.              !strcmp(szUserNameRequested,"anonymous")) {
  6574.             SendSRPAuthSB(SRP_REJECT, (void *)
  6575.             "anonymous login cannot be performed with Secure Remote Password",
  6576.             -1);
  6577.             auth_finished(AUTH_REJECT);
  6578.             return(AUTH_FAILURE);
  6579.         }
  6580. #endif /* CK_LOGIN */
  6581. #endif /* IKSD */
  6582. #ifndef PRE_SRP_1_4_4
  6583.         if(tpw == NULL) {
  6584.             if((tpw = t_openpw(NULL)) == NULL) {
  6585.                 if (1)
  6586.                     printf("Unable to open password file\r\n");
  6587.                 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
  6588.                 return(AUTH_FAILURE);
  6589.             }
  6590.         }
  6591.         if(tconf == NULL) {
  6592.             if((tconf = t_openconf(NULL)) == NULL) {
  6593.                 if (1)
  6594.                   printf("Unable to open configuration file\r\n");
  6595.                 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
  6596.                 return(AUTH_FAILURE);
  6597.             }
  6598.         }
  6599.         ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  6600.         t_closepw(tpw);
  6601.         tpw = NULL;
  6602.         t_closeconf(tconf);
  6603.         tconf = NULL;
  6604. #else /* PRE_SRP_1_4_4 */
  6605. #ifdef COMMENT
  6606.         /* the code in this block should no longer be necessary on OS/2
  6607.            or Windows because I have added functionality to libsrp.lib
  6608.            to find the srp files.   4/22/2000
  6609.         */
  6610.  
  6611.         /* On Windows and OS/2 there is no well defined place for the */
  6612.         /* ETC directory.  So we look for either an SRP_ETC or ETC    */
  6613.         /* environment variable in that order.  If we find one we     */
  6614.         /* attempt to open the files manually.                        */
  6615.         /* We will reuse the strTmp[] for the file names. */
  6616.         ptr = getenv("SRP_ETC");
  6617.         if ( !ptr )
  6618.             ptr = getenv("ETC");
  6619. #ifdef NT
  6620.         if ( !ptr ) {
  6621.             DWORD len;
  6622.             len = AUTHTMPBL;
  6623.  
  6624.             len = GetWindowsDirectory(strTmp,len);
  6625.             if ( len > 0 && len < AUTHTMPBL) {
  6626.                 if ( !isWin95() ) {
  6627.                     if ( len == 1 )
  6628.               ckstrncat(strTmp,"SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
  6629.                     else
  6630.               ckstrncat(strTmp,"/SYSTEM32/DRIVERS/ETC",sizeof(strTmp));
  6631.                 }
  6632.             }
  6633.             ptr = strTmp;
  6634.         }
  6635. #endif /* NT */
  6636.         if ( ptr ) {
  6637.             int len = strlen(ptr);
  6638.             int i;
  6639.         if (ptr != strTmp)
  6640.         strcpy(strTmp,ptr);
  6641.             for ( i=0;i<len;i++ ) {
  6642.                 if ( strTmp[i] == '\\' )
  6643.                     strTmp[i] = '/';
  6644.             }
  6645.             if ( strTmp[len-1] != '/' )
  6646.                 ckstrncat(strTmp,"/tpasswd",sizeof(strTmp));
  6647.             else
  6648.                 ckstrncat(strTmp,"tpasswd",sizeof(strTmp));
  6649.             tpw = t_openpwbyname(strTmp);
  6650.  
  6651.             ckstrncat(strTmp,".conf",sizeof(strTmp));
  6652.             tconf = t_openconfbyname(strTmp);
  6653.         }
  6654.  
  6655.         if ( tpw && tconf )
  6656.             ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  6657.         else
  6658.             ts = t_serveropen(szUserNameRequested);
  6659.         if ( tpw ) {
  6660.             t_closepw(tpw);
  6661.             tpw = NULL;
  6662.         }
  6663.         if ( tconf ) {
  6664.             t_closeconf(tconf);
  6665.             tconf = NULL;
  6666.         }
  6667. #else /* COMMENT */
  6668.         ts = t_serveropen(szUserNameRequested);
  6669. #endif /* COMMENT */
  6670. #endif /* PRE_SRP_1_4_4 */
  6671.  
  6672.         if( ts == NULL ) {
  6673.             printf("User %s not found\r\n", szUserNameRequested);
  6674.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  6675.             return(AUTH_FAILURE);
  6676.         }
  6677.  
  6678.     pbuf = (char *)malloc(ts->n.len + ts->g.len + ts->s.len + 7);
  6679.     ptr = pbuf;
  6680.  
  6681.         srp_encode_length(ptr, ts->n.len);
  6682.         ptr += 2;
  6683.         memcpy(ptr, ts->n.data, ts->n.len);     /* safe */
  6684.         ptr += ts->n.len;
  6685.  
  6686.         srp_encode_length(ptr, ts->g.len);
  6687.         ptr += 2;
  6688.         memcpy(ptr, ts->g.data, ts->g.len);     /* safe */
  6689.         ptr += ts->g.len;
  6690.  
  6691.         srp_encode_length(ptr, ts->s.len);
  6692.         ptr += 2;
  6693.         memcpy(ptr, ts->s.data, ts->s.len);     /* safe */
  6694.         ptr += ts->s.len;
  6695.  
  6696.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  6697.     free(pbuf); pbuf = NULL;
  6698.  
  6699.         B = t_servergenexp(ts);
  6700.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
  6701.         return AUTH_SUCCESS;
  6702.  
  6703.     case SRP_EXP:
  6704.         /* Client is sending A to us, compute challenge & expected response. */
  6705.         if (ts == NULL || B == NULL) {
  6706.             printf("Protocol error: SRP_EXP unexpected\r\n");
  6707.             SendSRPAuthSB(SRP_REJECT,
  6708.                           (void *) "Protocol error: unexpected EXP",
  6709.                           -1
  6710.                           );
  6711.             return(AUTH_FAILURE);
  6712.         }
  6713.  
  6714.         /* Wait until now to send B, since it contains the key to "u" */
  6715.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
  6716.         B = NULL;
  6717.  
  6718. #ifndef PRE_SRP_1_4_5
  6719.         /*
  6720.          * The original SRP AUTH implementation did not protect against
  6721.          * tampering of the auth-type-pairs.  Therefore, when the
  6722.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6723.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6724.          * is set we also insert the SSL/TLS client and server finished
  6725.          * messages to ensure that there is no man in the middle attack
  6726.          * underway on the SSL/TLS connection.
  6727.          */
  6728.         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
  6729.             type_check[0] = AUTHTYPE_SRP;
  6730.             type_check[1] = how;
  6731. #ifdef CK_SSL
  6732.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6733.                 ssl_get_client_finished(&type_check[2],12);
  6734.                 ssl_get_server_finished(&type_check[14],12);
  6735.             }
  6736. #endif /* CK_SSL */
  6737.             t_serveraddexdata(ts,type_check,
  6738. #ifdef CK_SSL
  6739.                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  6740. #endif /* CK_SSL */
  6741.                                2);
  6742.         }
  6743. #endif /* PRE_SRP_1_4_5 */
  6744.  
  6745.         A.data = data;
  6746.         A.len = cnt;
  6747.         ptr = t_servergetkey(ts, &A);
  6748.  
  6749.         if(ptr == NULL) {
  6750.             if (1)
  6751.               printf("Security alert: Trivial session key attempted\r\n");
  6752.             SendSRPAuthSB(SRP_REJECT,
  6753.                           (void *) "Trivial session key detected",
  6754.                           -1
  6755.                           );
  6756.             return(AUTH_FAILURE);
  6757.         }
  6758.         srp_waitresp = 1;
  6759.         return AUTH_SUCCESS;
  6760.  
  6761.     case SRP_RESPONSE:
  6762.         /* Got the response; see if it's correct */
  6763.         if (!srp_waitresp ||
  6764.              ts == NULL
  6765.              ) {
  6766.             if (1)
  6767.               printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  6768.             SendSRPAuthSB(SRP_REJECT,
  6769.                           (void *) "Protocol error: unexpected RESPONSE",
  6770.                           -1
  6771.                           );
  6772.             return(AUTH_FAILURE);
  6773.         }
  6774.         srp_waitresp = 0;       /* we got a response */
  6775.  
  6776.         if (cnt < RESPONSE_LEN) {
  6777.             if (1)
  6778.               printf("Protocol error: malformed response\r\n");
  6779.             SendSRPAuthSB(SRP_REJECT,
  6780.                           (void *) "Protocol error: malformed response",
  6781.                           -1
  6782.                           );
  6783.             return(AUTH_FAILURE);
  6784.         }
  6785.  
  6786.         if (t_serververify(ts, data) == 0) {
  6787.             SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
  6788.             accept_complete = 1;
  6789. #ifdef CK_ENCRYPTION
  6790. #ifdef CK_SSL
  6791.             if (!(ssl_active_flag || tls_active_flag))
  6792. #endif /* CK_SSL */
  6793.             {
  6794.                 ckhexdump("SRP_RESPONSE ts",ts,sizeof(ts));
  6795.                 ckhexdump("SRP_RESPONSE session_key",
  6796.                          ts->session_key,
  6797.                          SESSION_KEY_LEN
  6798.                          );
  6799.                 skey.type = SK_GENERIC;
  6800.                 skey.length = SESSION_KEY_LEN;
  6801.                 skey.data = ts->session_key;
  6802.                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  6803.             }
  6804. #endif /* CK_ENCRYPTION */
  6805.             auth_finished(AUTH_VALID);
  6806.         }
  6807.         else {
  6808.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  6809.             auth_finished(AUTH_REJECT);
  6810.             return(AUTH_FAILURE);
  6811.         }
  6812.         return AUTH_SUCCESS;
  6813.  
  6814.     default:
  6815.         printf("Unknown SRP option %d\r\n", data[-1]);
  6816.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  6817.         return(AUTH_FAILURE);
  6818.     }
  6819. }
  6820. #else /* PRE_SRP_1_7_3 */
  6821. static int
  6822. #ifdef CK_ANSIC
  6823. new_srp_reply(int how, unsigned char *data, int cnt)
  6824. #else
  6825. new_srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  6826. #endif
  6827. {
  6828.     data += 4;                          /* Point to status byte */
  6829.     cnt  -= 4;
  6830.  
  6831.     if(cnt-- < 1) {                     /* Matches with data++ */
  6832.         auth_finished(AUTH_REJECT);
  6833.         return AUTH_FAILURE;
  6834.     }
  6835.  
  6836.     switch(*data++) {
  6837.     case SRP_PARAMS: {
  6838.         struct t_num n;
  6839.         struct t_num g;
  6840.         struct t_num s;
  6841.         cstr * A;
  6842.  
  6843.         if(!szUserName) {
  6844.             printf("No username available\r\n");
  6845.             return(auth_resend(AUTHTYPE_SRP));
  6846.         }
  6847.  
  6848.         n.len = srp_decode_length(data);
  6849.         data += 2;
  6850.         cnt -= 2;
  6851.         if(n.len > cnt) {
  6852.             printf("n too long\r\n");
  6853.             return(auth_resend(AUTHTYPE_SRP));
  6854.         }
  6855.         n.data = data;
  6856.         data += n.len;
  6857.         cnt -= n.len;
  6858.  
  6859.         g.len = srp_decode_length(data);
  6860.         data += 2;
  6861.         cnt -= 2;
  6862.         if(g.len > cnt) {
  6863.             printf("g too long\r\n");
  6864.             return(auth_resend(AUTHTYPE_SRP));
  6865.         }
  6866.         g.data = data;
  6867.         data += g.len;
  6868.         cnt -= g.len;
  6869.  
  6870.         s.len = srp_decode_length(data);
  6871.         data += 2;
  6872.         cnt -= 2;
  6873.         if(s.len != cnt) {
  6874.             printf("invalid salt\r\n");
  6875.             return(auth_resend(AUTHTYPE_SRP));
  6876.         }
  6877.         s.data = data;
  6878.         data += s.len;
  6879.         cnt -= s.len;
  6880.  
  6881.         /* If the parameters provided by the server cannot be
  6882.          * validated the following function will fail.
  6883.          */
  6884.         c_srp = SRP_new(SRP_RFC2945_client_method());
  6885.         if (c_srp == NULL ||
  6886.         SRP_set_username(c_srp, szUserName) != SRP_SUCCESS ||
  6887.         SRP_set_params(c_srp,n.data,n.len,g.data,g.len,s.data,s.len) !=
  6888.         SRP_SUCCESS) {
  6889.             printf("SRP Parameter initialization error\r\n");
  6890.             return(auth_resend(AUTHTYPE_SRP));
  6891.         }
  6892.  
  6893.         A = cstr_new();
  6894.         if(SRP_gen_pub(c_srp, &A) != SRP_SUCCESS) {
  6895.             printf("SRP Error generating key exchange\r\n");
  6896.             return(auth_resend(AUTHTYPE_SRP));
  6897.         }
  6898.  
  6899.         SendSRPAuthSB(SRP_EXP, A->data, A->length);
  6900.         cstr_free(A);
  6901.  
  6902.         if ( pwbuf[0] && pwflg ) {
  6903.             printf("SRP using %d-bit modulus for '%s'\r\n",
  6904.                    8 * n.len,
  6905.                    szUserName
  6906.                    );
  6907.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  6908. #ifdef OS2
  6909.             if ( pwcrypt )
  6910.                 ck_encrypt((char *)srp_passwd);
  6911. #endif /* OS2 */
  6912.         } else {
  6913.             extern char * srppwprompt;
  6914.             char preface[128];
  6915.             int ok;
  6916.  
  6917.             if (srppwprompt && srppwprompt[0] &&
  6918.         (strlen(srppwprompt) + strlen(szUserName) - 2) <
  6919.         sizeof(preface)) {
  6920.                 sprintf(preface,srppwprompt,szUserName);
  6921.             } else {
  6922.                 ckmakxmsg( preface,sizeof(preface),
  6923.                           "SRP using ",ckitoa(8*n.len),"-bit modulus for '",
  6924.                           szUserName, "'", NULL, NULL, NULL, NULL, NULL,
  6925.                           NULL, NULL);
  6926.             }
  6927.             ok = uq_txt(preface,"Password: ",2,NULL,
  6928.                         srp_passwd,sizeof(srp_passwd)-1,NULL,
  6929.             DEFAULT_UQ_TIMEOUT);
  6930.             if ( !ok )
  6931.                 srp_passwd[0] = '\0';
  6932.         }
  6933.  
  6934.         if(SRP_set_auth_password(c_srp, srp_passwd) != SRP_SUCCESS) {
  6935.             memset(srp_passwd, 0, sizeof(srp_passwd));
  6936.             printf("SRP Error setting client password\r\n");
  6937.             return(auth_resend(AUTHTYPE_SRP));
  6938.         }
  6939.         memset(srp_passwd, 0, sizeof(srp_passwd));
  6940.         return AUTH_SUCCESS;
  6941.     }
  6942.     case SRP_CHALLENGE: {
  6943.         char type_check[26];
  6944.         cstr * resp = NULL;
  6945.  
  6946.         if(c_srp == NULL) {
  6947.             printf("SRP protocol error\r\n");
  6948.             return(auth_resend(AUTHTYPE_SRP));
  6949.         }
  6950.  
  6951.         /*
  6952.          * The original SRP AUTH implementation did not protect against
  6953.          * tampering of the auth-type-pairs.  Therefore, when the
  6954.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6955.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6956.          * is set we also insert the SSL/TLS client and server finished
  6957.          * messages to ensure that there is no man in the middle attack
  6958.          * underway on the SSL/TLS connection.
  6959.          */
  6960.         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
  6961.             type_check[0] = AUTHTYPE_SRP;
  6962.             type_check[1] = how;
  6963. #ifdef CK_SSL
  6964.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6965.                 ssl_get_client_finished(&type_check[2],12);
  6966.                 ssl_get_server_finished(&type_check[14],12);
  6967.                 SRP_add_ex_data(c_srp, type_check, 26);
  6968.             } else
  6969. #endif /* CK_SSL */
  6970.                 SRP_add_ex_data(c_srp, type_check, 2);
  6971.         }
  6972.  
  6973.         if(SRP_compute_key(c_srp, &c_key, data, cnt) != SRP_SUCCESS) {
  6974.             printf("SRP ERROR: unable to compute client key\r\n");
  6975.             return(auth_resend(AUTHTYPE_SRP));
  6976.         }
  6977.  
  6978.         resp = cstr_new();
  6979.         if(SRP_respond(c_srp, &resp) != SRP_SUCCESS) {
  6980.             printf("SRP ERROR: unable to compute client response\r\n");
  6981.             return(auth_resend(AUTHTYPE_SRP));
  6982.         }
  6983.         SendSRPAuthSB(SRP_RESPONSE, resp->data, resp->length);
  6984.         cstr_free(resp);
  6985.         srp_waitresp = 1;
  6986.         return AUTH_SUCCESS;
  6987.     }
  6988.     case SRP_ACCEPT: {
  6989. #ifdef CK_ENCRYPTION
  6990.         Session_Key skey;
  6991. #endif /* ENCRYPTION */
  6992.  
  6993.         if(cnt < RESPONSE_LEN || !srp_waitresp || c_srp == NULL) {
  6994.             printf("SRP Protocol error\r\n");
  6995.             return(auth_resend(AUTHTYPE_SRP));
  6996.         }
  6997.         srp_waitresp = 0;
  6998.  
  6999.         if(SRP_verify(c_srp, data, cnt) == SRP_SUCCESS) {
  7000.             printf("SRP accepts you as %s\r\n",szUserName);
  7001.  
  7002. #ifdef CK_SSL
  7003.             if((ssl_active_flag || tls_active_flag) &&
  7004.                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  7005.                 printf("TLS session parameters verified by SRP\r\n");
  7006.             } else
  7007. #endif /* CK_SSL */
  7008. #ifdef CK_ENCRYPTION
  7009.             {
  7010.                 skey.type = SK_GENERIC;
  7011.                 skey.length = c_key->length;
  7012.                 skey.data = c_key->data;
  7013.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  7014.                 cstr_clear_free(c_key);
  7015.                 c_key = NULL;
  7016.             }
  7017. #endif /* CK_ENCRYPTION */
  7018.             accept_complete = 1;
  7019.             auth_finished(AUTH_VALID);
  7020.             SRP_free(c_srp);
  7021.             c_srp = NULL;
  7022.             return AUTH_SUCCESS;
  7023.         }
  7024.         else {
  7025.             printf("[ Error: SRP server authentication failed ]\r\n");
  7026.             return(auth_resend(AUTHTYPE_SRP));
  7027.         }
  7028.     }
  7029.     case SRP_REJECT: {
  7030.         char * str=NULL;
  7031.  
  7032.         ckmakmsg(strTmp,sizeof(strTmp),
  7033.                   "SRP refuses authentication for '",szUserName,
  7034.                   "'\r\n",NULL);
  7035.         if (cnt > 0) {
  7036.             int len = strlen(strTmp);
  7037.             if ( len + cnt < sizeof(strTmp) ) {
  7038.                 str = strTmp + strlen(strTmp);
  7039.                 memcpy(str,data,cnt);
  7040.                 str[cnt] = 0;
  7041.             }
  7042.         }
  7043.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  7044.         auth_finished(AUTH_REJECT);
  7045.         return AUTH_FAILURE;
  7046.     }
  7047.     default:
  7048.         printf("Unknown SRP option %d\r\n", data[-1]);
  7049.         return(auth_resend(AUTHTYPE_SRP));
  7050.     }
  7051.     /* NEVER REACHED */
  7052. }
  7053.  
  7054. static int
  7055. #ifdef CK_ANSIC
  7056. new_srp_is(int how, unsigned char *data, int cnt)
  7057. #else
  7058. new_srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  7059. #endif
  7060. {
  7061.     char * pbuf = NULL;
  7062.     char * ptr;
  7063. #ifdef CK_ENCRYPTION
  7064.     Session_Key skey;
  7065. #endif
  7066.     static cstr * B = NULL;             /* Holder for B */
  7067.     struct t_passwd * pass;
  7068.     cstr * resp;
  7069.     char type_check[26];
  7070.  
  7071.     if ((cnt -= 4) < 1) {
  7072.         auth_finished(AUTH_REJECT);
  7073.         return AUTH_FAILURE;
  7074.     }
  7075.  
  7076.     data += 4;
  7077.     cnt  -= 1;
  7078.     switch(*data++) {
  7079.     case SRP_AUTH:
  7080.         /* Send parameters back to client */
  7081.         if(s_srp != NULL) {
  7082.             SRP_free(s_srp);
  7083.             s_srp = NULL;
  7084.         }
  7085.         if (B != NULL) {
  7086.             cstr_free(B);
  7087.             B = NULL;
  7088.         }
  7089.         if(!szUserNameRequested[0]) {
  7090.             if (1)
  7091.                 printf("No username available\r\n");
  7092.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  7093.             auth_finished(AUTH_REJECT);
  7094.             return(AUTH_FAILURE);
  7095.         }
  7096. #ifdef IKSD
  7097. #ifdef CK_LOGIN
  7098.         if (inserver && ckxanon &&
  7099.              !strcmp(szUserNameRequested,"anonymous")) {
  7100.             SendSRPAuthSB(SRP_REJECT, (void *)
  7101.             "anonymous login cannot be performed with Secure Remote Password",
  7102.             -1);
  7103.             auth_finished(AUTH_REJECT);
  7104.             return(AUTH_FAILURE);
  7105.         }
  7106. #endif /* CK_LOGIN */
  7107. #endif /* IKSD */
  7108.         s_srp = SRP_new(SRP_RFC2945_server_method());
  7109.         if(s_srp == NULL) {
  7110.             printf("Error initializing SRP server\r\n");
  7111.             SendSRPAuthSB(SRP_REJECT,
  7112.                           (void *) "SRP server init failed",
  7113.                           -1
  7114.                           );
  7115.             return(AUTH_FAILURE);
  7116.         }
  7117.         pass = gettpnam(szUserNameRequested);
  7118.         if(pass == NULL) {
  7119.             printf("User %s not found\r\n", szUserNameRequested);
  7120.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  7121.             return(AUTH_FAILURE);
  7122.         }
  7123.         if(SRP_set_username(s_srp, szUserNameRequested) != SRP_SUCCESS ||
  7124.        SRP_set_params(s_srp, pass->tc.modulus.data,
  7125.               pass->tc.modulus.len,
  7126.               pass->tc.generator.data,
  7127.               pass->tc.generator.len,
  7128.               pass->tp.salt.data,
  7129.               pass->tp.salt.len) != SRP_SUCCESS ||
  7130.        SRP_set_authenticator(s_srp,
  7131.                  pass->tp.password.data,
  7132.                  pass->tp.password.len) != SRP_SUCCESS) {
  7133.             printf("Error initializing SRP parameters\r\n");
  7134.             SendSRPAuthSB(SRP_REJECT,(void *)"SRP parameter init failed", -1);
  7135.             return(AUTH_FAILURE);
  7136.         }
  7137.  
  7138.     pbuf = (char *)malloc(pass->tc.modulus.len + pass->tc.generator.len +
  7139.                    pass->tp.salt.len + 7);
  7140.         ptr = pbuf;
  7141.  
  7142.         srp_encode_length(ptr, pass->tc.modulus.len);
  7143.         ptr += 2;
  7144.         memcpy(ptr, pass->tc.modulus.data, pass->tc.modulus.len);
  7145.         ptr += pass->tc.modulus.len;
  7146.  
  7147.         srp_encode_length(ptr, pass->tc.generator.len);
  7148.         ptr += 2;
  7149.         memcpy(ptr, pass->tc.generator.data, pass->tc.generator.len);
  7150.         ptr += pass->tc.generator.len;
  7151.  
  7152.         srp_encode_length(ptr, pass->tp.salt.len);
  7153.         ptr += 2;
  7154.         memcpy(ptr, pass->tp.salt.data, pass->tp.salt.len);
  7155.         ptr += pass->tp.salt.len;
  7156.  
  7157.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  7158.     free(pbuf);
  7159.     pbuf = NULL;
  7160.  
  7161.         if(SRP_gen_pub(s_srp, &B) != SRP_SUCCESS) {
  7162.             printf("Error generating SRP public value\r\n");
  7163.             SendSRPAuthSB(SRP_REJECT, (void *) "SRP_gen_pub failed", -1);
  7164.             return(AUTH_FAILURE);
  7165.         }
  7166.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
  7167.         return AUTH_SUCCESS;
  7168.  
  7169.     case SRP_EXP:
  7170.       /* Client is sending A to us, compute challenge and expected response. */
  7171.         if (s_srp == NULL || B == NULL) {
  7172.         printf("Protocol error: SRP_EXP unexpected\r\n");
  7173.         SendSRPAuthSB(SRP_REJECT,
  7174.               (void *)"Protocol error: unexpected EXP", -1);
  7175.         return(AUTH_FAILURE);
  7176.     }
  7177.         /* Wait until now to send B, since it contains the key to "u" */
  7178.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->length);
  7179.         cstr_free(B);
  7180.         B = NULL;
  7181.  
  7182.         /*
  7183.          * The original SRP AUTH implementation did not protect against
  7184.          * tampering of the auth-type-pairs.  Therefore, when the
  7185.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  7186.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  7187.          * is set we also insert the SSL/TLS client and server finished
  7188.          * messages to ensure that there is no man in the middle attack
  7189.          * underway on the SSL/TLS connection.
  7190.          */
  7191.         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
  7192.             type_check[0] = AUTHTYPE_SRP;
  7193.             type_check[1] = how;
  7194. #ifdef CK_SSL
  7195.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  7196.                 ssl_get_client_finished(&type_check[2],12);
  7197.                 ssl_get_server_finished(&type_check[14],12);
  7198.                 SRP_add_ex_data(s_srp, type_check, 26);
  7199.             } else
  7200. #endif /* CK_SSL */
  7201.                 SRP_add_ex_data(s_srp, type_check, 2);
  7202.         }
  7203.  
  7204.         if(SRP_compute_key(s_srp, &s_key, data, cnt) != SRP_SUCCESS) {
  7205.             printf("Security alert: Trivial session key attempted\r\n");
  7206.             SendSRPAuthSB(SRP_REJECT,
  7207.               (void *) "Trivial session key detected", -1);
  7208.             return(AUTH_FAILURE);
  7209.         }
  7210.         srp_waitresp = 1;
  7211.         return AUTH_SUCCESS;
  7212.  
  7213.     case SRP_RESPONSE:
  7214.         /* Got the response; see if it's correct */
  7215.         if (!srp_waitresp || s_srp == NULL) {
  7216.             if (1)
  7217.               printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  7218.             SendSRPAuthSB(SRP_REJECT,
  7219.                           (void *) "Protocol error: unexpected RESPONSE",
  7220.                           -1
  7221.                           );
  7222.             return(AUTH_FAILURE);
  7223.         }
  7224.         srp_waitresp = 0;       /* we got a response */
  7225.  
  7226.         if (cnt < RESPONSE_LEN) {
  7227.             if (1)
  7228.               printf("Protocol error: malformed response\r\n");
  7229.             SendSRPAuthSB(SRP_REJECT,
  7230.                           (void *) "Protocol error: malformed response",
  7231.                           -1
  7232.                           );
  7233.             return(AUTH_FAILURE);
  7234.         }
  7235.  
  7236.         if(SRP_verify(s_srp, data, cnt) == SRP_SUCCESS) {
  7237.             resp = cstr_new();
  7238.             if(SRP_respond(s_srp, &resp) != SRP_SUCCESS) {
  7239.                 printf("Error computing response\r\n");
  7240.                 SendSRPAuthSB(SRP_REJECT,
  7241.                               (void *) "Error computing response", -1);
  7242.                 return(AUTH_FAILURE);
  7243.             }
  7244.             SendSRPAuthSB(SRP_ACCEPT, resp->data, resp->length);
  7245.             accept_complete = 1;
  7246.             cstr_free(resp);
  7247.  
  7248. #ifdef CK_ENCRYPTION
  7249. #ifdef CK_SSL
  7250.             if (!(ssl_active_flag || tls_active_flag))
  7251. #endif /* CK_SSL */
  7252.             {
  7253.                 skey.type = SK_GENERIC;
  7254.                 skey.length = s_key->length;
  7255.                 skey.data = s_key->data;
  7256.                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  7257.                 cstr_clear_free(s_key);
  7258.                 s_key = NULL;
  7259.             }
  7260. #endif /* CK_ENCRYPTION */
  7261.             auth_finished(AUTH_VALID);
  7262.         }
  7263.         else {
  7264.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  7265.             auth_finished(AUTH_REJECT);
  7266.             return(AUTH_FAILURE);
  7267.         }
  7268.         return AUTH_SUCCESS;
  7269.  
  7270.     default:
  7271.         printf("Unknown SRP option %d\r\n", data[-1]);
  7272.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  7273.         return(AUTH_FAILURE);
  7274.     }
  7275. }
  7276. #endif /* PRE_SRP_1_7_3 */
  7277. #endif /* SRP */
  7278.  
  7279. #ifdef KRB5
  7280. #ifdef KINIT
  7281. /*
  7282.  * clients/kinit/kinit.c
  7283.  *
  7284.  * Copyright 1990 by the Massachusetts Institute of Technology.
  7285.  * All Rights Reserved.
  7286.  *
  7287.  * Export of this software from the United States of America may
  7288.  *   require a specific license from the United States Government.
  7289.  *   It is the responsibility of any person or organization contemplating
  7290.  *   export to obtain such a license before exporting.
  7291.  *
  7292.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  7293.  * distribute this software and its documentation for any purpose and
  7294.  * without fee is hereby granted, provided that the above copyright
  7295.  * notice appear in all copies and that both that copyright notice and
  7296.  * this permission notice appear in supporting documentation, and that
  7297.  * the name of M.I.T. not be used in advertising or publicity pertaining
  7298.  * to distribution of the software without specific, written prior
  7299.  * permission.  M.I.T. makes no representations about the suitability of
  7300.  * this software for any purpose.  It is provided "as is" without express
  7301.  * or implied warranty.
  7302.  *
  7303.  *
  7304.  * Initialize a credentials cache.
  7305.  */
  7306.  
  7307. #define KRB5_DEFAULT_OPTIONS 0
  7308. #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
  7309.  
  7310. static krb5_data tgtname = {
  7311. #ifndef HEIMDAL
  7312.     0,
  7313. #endif /* HEIMDAL */
  7314.     KRB5_TGS_NAME_SIZE,
  7315.     KRB5_TGS_NAME
  7316. };
  7317.  
  7318. /* Internal prototypes */
  7319. _PROTOTYP(static krb5_error_code krb5_validate_tgt,
  7320.         (krb5_context, krb5_ccache,krb5_principal, krb5_data *));
  7321. _PROTOTYP(static krb5_error_code krb5_renew_tgt,
  7322.         (krb5_context, krb5_ccache,
  7323.                         krb5_principal, krb5_data *));
  7324. _PROTOTYP(static krb5_error_code krb5_tgt_gen,
  7325.         (krb5_context, krb5_ccache,
  7326.                         krb5_principal, krb5_data *, int opt));
  7327.  
  7328. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7329. static krb5_error_code KRB5_CALLCONV
  7330. ck_krb5_prompter( krb5_context context,
  7331.                   void *data,
  7332.                   const char *name,
  7333.                   const char *banner,
  7334.                   int num_prompts,
  7335.                   krb5_prompt prompts[])
  7336. {
  7337.     krb5_error_code     errcode = 0;
  7338.     int                 i;
  7339. #ifdef KUI
  7340.     struct txtbox * tb = NULL;
  7341. #else /* KUI */
  7342.     char * prompt = NULL;
  7343. #endif /* KUI */
  7344.     int    len = 0, blen=0, nlen=0;
  7345.  
  7346.     debug(F110,"ck_krb5_prompter name",name,0);
  7347.     debug(F110,"ck_krb5_prompter banner",banner,0);
  7348.     debug(F101,"ck_krb5_prompter num_prompts","",num_prompts);
  7349.  
  7350.     if (name)
  7351.         nlen = strlen(name)+2;
  7352.  
  7353.     if (banner)
  7354.         blen = strlen(banner)+2;
  7355.  
  7356. #ifdef KUI
  7357.     tb = (struct txtbox *) malloc(sizeof(struct txtbox) * num_prompts);
  7358.     if ( tb != NULL ) {
  7359.         int ok;
  7360.         memset(tb,0,sizeof(struct txtbox) * num_prompts);
  7361.         for ( i=0; i < num_prompts; i++ ) {
  7362.             tb[i].t_buf = prompts[i].reply->data;
  7363.             tb[i].t_len = prompts[i].reply->length;
  7364.             tb[i].t_lbl = prompts[i].prompt;
  7365.             tb[i].t_dflt = NULL;
  7366.             tb[i].t_echo = (prompts[i].hidden ? 2 : 1);
  7367.         }   
  7368.  
  7369.         ok = uq_mtxt((char *)banner,NULL,num_prompts,tb);
  7370.         if ( ok ) {
  7371.             for ( i=0; i < num_prompts; i++ )
  7372.                 prompts[i].reply->length = strlen(prompts[i].reply->data);
  7373.         } else
  7374.             errcode = -2;
  7375.     }
  7376. #else /* KUI */
  7377.     for (i = 0; i < num_prompts; i++) {
  7378.         debug(F111,"ck_krb5_prompter prompt",prompts[i].prompt,i);
  7379.  
  7380.         if ( prompt && len < (nlen + blen + strlen(prompts[i].prompt)+2) ) {
  7381.             free(prompt);
  7382.             prompt = NULL;
  7383.         }
  7384.         if ( !prompt )
  7385.             prompt = (char *)malloc(nlen + blen + strlen(prompts[i].prompt)+2);
  7386.         if ( !prompt ) {
  7387.             errcode = KRB5_RC_MALLOC;
  7388.             goto cleanup;
  7389.         }
  7390.         len = nlen + blen + strlen(prompts[i].prompt)+2;
  7391.         ckmakxmsg(prompt,len,
  7392.                  (char *) (name?name:""),
  7393.                  name?"\r\n":"",
  7394.                  (char *) (banner?banner:""),
  7395.                  banner?"\r\n":"",
  7396.                  (char *)prompts[i].prompt,
  7397.                  ": ",NULL,NULL,NULL,NULL,NULL,NULL);
  7398.  
  7399.         memset(prompts[i].reply->data, 0, prompts[i].reply->length);
  7400.         if (prompts[i].hidden) {
  7401.             readpass(prompt, prompts[i].reply->data,
  7402.                       prompts[i].reply->length);
  7403.         } else {
  7404.             readtext(prompt, prompts[i].reply->data,
  7405.                       prompts[i].reply->length);
  7406.         }
  7407.         prompts[i].reply->length = strlen(prompts[i].reply->data);
  7408.     }
  7409. #endif /* KUI */
  7410.  
  7411.   cleanup:
  7412. #ifdef KUI
  7413.     if ( tb )
  7414.         free(tb);
  7415. #else /* KUI */
  7416.     if ( prompt )
  7417.         free(prompt);
  7418. #endif /* KUI */
  7419.     if (errcode) {
  7420.         for (i = 0; i < num_prompts; i++) {
  7421.             memset(prompts[i].reply->data, 0, prompts[i].reply->length);
  7422.         }
  7423.     }
  7424.     return errcode;
  7425. }
  7426.  
  7427. /*
  7428.  *      I'm not really sure what to do with this.  The NRL DLLs use a
  7429.  *      different interface for the krb5_prompter callback.  It has
  7430.  *      one less parameter.   This is going to be ugly.
  7431.  */
  7432. static krb5_error_code KRB5_CALLCONV
  7433. ck_NRL_krb5_prompter( krb5_context context,
  7434.                       const char *name,
  7435.                       const char *banner,
  7436.                       int num_prompts,
  7437.                       krb5_prompt prompts[])
  7438. {
  7439.     return(ck_krb5_prompter(context,NULL,name,banner,num_prompts,prompts));
  7440. }
  7441. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7442.  
  7443. #ifdef KRB524_CONV
  7444. long
  7445. try_convert524(krb5_context ctx, krb5_principal me, krb5_ccache cc)
  7446. {
  7447.     char * progname = "convert524";
  7448.     krb5_error_code code = 0;
  7449.     int icode = 0;
  7450.     krb5_principal kpcserver = 0;
  7451.     krb5_creds *v5creds = 0;
  7452.     krb5_creds increds;
  7453. #ifdef OS2
  7454.     LEASH_CREDENTIALS v4creds;
  7455. #else /* OS2 */
  7456.     CREDENTIALS v4creds;
  7457. #endif /* OS2 */
  7458.  
  7459.     memset((char *) &increds, 0, sizeof(increds));
  7460.     /*
  7461.       From this point on, we can goto cleanup because increds is
  7462.       initialized.
  7463.     */
  7464.  
  7465.     if ((code = krb5_build_principal(ctx,
  7466.                                      &kpcserver,
  7467.                                      krb5_princ_realm(ctx, me)->length,
  7468.                                      krb5_princ_realm(ctx, me)->data,
  7469.                                      "krbtgt",
  7470.                                      krb5_princ_realm(ctx, me)->data,
  7471.                                      NULL))) {
  7472.         com_err(progname, code,
  7473.                 "while creating service principal name");
  7474.         goto cleanup;
  7475.     }
  7476.  
  7477.     memset((char*) &increds, 0, sizeof(increds));
  7478.     increds.client = me;
  7479.     increds.server = kpcserver;
  7480.     /* Prevent duplicate free calls.  */
  7481.     kpcserver = 0;
  7482.  
  7483.     increds.times.endtime = 0;
  7484.     increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
  7485.     if ((code = krb5_get_credentials(ctx, 0,
  7486.                                      cc,
  7487.                                      &increds,
  7488.                                      &v5creds))) {
  7489.         com_err(progname, code,
  7490.                 "getting V5 credentials");
  7491.         goto cleanup;
  7492.     }
  7493.     if ((icode = krb524_convert_creds_kdc(ctx,
  7494.                                           v5creds,
  7495.                                           &v4creds))) {
  7496.         com_err(progname, icode,
  7497.                 "converting to V4 credentials");
  7498.         goto cleanup;
  7499.     }
  7500.     /* this is stolen from the v4 kinit */
  7501.     /* initialize ticket cache */
  7502.     if ((icode = krb_in_tkt(v4creds.pname, v4creds.pinst, v4creds.realm)
  7503.          != KSUCCESS)) {
  7504.         com_err(progname, icode,
  7505.                 "trying to create the V4 ticket file");
  7506.         goto cleanup;
  7507.     }
  7508.     /* stash ticket, session key, etc. for future use */
  7509.     if ((icode = krb_save_credentials(v4creds.service,
  7510.                                       v4creds.instance,
  7511.                                       v4creds.realm,
  7512.                                       v4creds.session,
  7513.                                       v4creds.lifetime,
  7514.                                       v4creds.kvno,
  7515.                                       &(v4creds.ticket_st),
  7516.                                       v4creds.issue_date))) {
  7517.         com_err(progname, icode,
  7518.                 "trying to save the V4 ticket");
  7519.         goto cleanup;
  7520.     }
  7521.  
  7522.  cleanup:
  7523.     memset(&v4creds, 0, sizeof(v4creds));
  7524.     if (v5creds)
  7525.         krb5_free_creds(ctx, v5creds);
  7526.     increds.client = 0;
  7527.     krb5_free_cred_contents(ctx, &increds);
  7528.     if (kpcserver)
  7529.         krb5_free_principal(ctx, kpcserver);
  7530.     return !(code || icode);
  7531. }
  7532. #endif /* KRB524_CONV */
  7533.  
  7534. #define NO_KEYTAB
  7535.  
  7536. int
  7537. #ifdef CK_ANSIC
  7538. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
  7539.                  struct krb4_init_data * k4_init)
  7540. #else
  7541. ck_krb5_initTGT(op,init,k4_init)
  7542.     krb_op_data * op; struct krb5_init_data * init;
  7543.     struct krb4_init_data * k4_init;
  7544. #endif /* CK_ANSIC*/
  7545. {
  7546.     krb5_context kcontext;
  7547.     krb5_ccache ccache = NULL;
  7548.     krb5_deltat lifetime = KRB5_DEFAULT_LIFE;   /* -l option */
  7549.     krb5_timestamp starttime = 0;
  7550.     krb5_deltat rlife = 0;
  7551.     int options = KRB5_DEFAULT_OPTIONS;
  7552.     int option;
  7553.     int errflg = 0;
  7554.     krb5_error_code code;
  7555.     krb5_principal me=NULL;
  7556.     krb5_principal server=NULL;
  7557.     krb5_creds my_creds;
  7558.     krb5_timestamp now;
  7559. #ifndef HEIMDAL
  7560.     krb5_address **addrs = (krb5_address **)0;
  7561. #endif /* HEIMDAL */
  7562.     int addr_count=0;
  7563.     int i,j;
  7564. #ifndef NO_KEYTAB
  7565.     int use_keytab = 0;                 /* -k option */
  7566.     krb5_keytab keytab = NULL;
  7567. #endif /* NO_KEYTAB */
  7568.     struct passwd *pw = 0;
  7569.     int pwsize;
  7570.     char *client_name=NULL, principal[256]="", realm[256]="", numstr[40]="";
  7571.     char *password=NULL, passwd[80]="";
  7572. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7573.     krb5_get_init_creds_opt opts;
  7574. #endif
  7575.     char * name;
  7576.     int len;
  7577.  
  7578.     if ( !ck_krb5_is_installed() )
  7579.         return(-1);
  7580.  
  7581. #ifdef COMMENT
  7582.     printf("Kerberos V initialization\r\n");
  7583. #endif /* COMMENT */
  7584.  
  7585.     code = krb5_init_context(&kcontext);
  7586.     if (code) {
  7587.         com_err("krb5_kinit",code,"while init_context");
  7588.         krb5_errno = code;
  7589.         makestr(&krb5_errmsg,error_message(krb5_errno));
  7590.         return(-1);
  7591.     }
  7592.  
  7593.     debug(F110,"krb5_init","krb5_init_context",0);
  7594.  
  7595.     if ((code = krb5_timeofday(kcontext, &now))) {
  7596.         com_err("krb5_kinit",code,"while getting time of day");
  7597.         goto exit_k5_init;
  7598.     }
  7599.  
  7600. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7601.     memset(&opts, 0, sizeof(opts));
  7602.     krb5_get_init_creds_opt_init(&opts);
  7603.     debug(F110,"krb5_init","krb5_get_init_creds_opt_init",0);
  7604. #endif
  7605.  
  7606.     if ( init->renewable ) {
  7607.         options |= KDC_OPT_RENEWABLE;
  7608.         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->renewable),"m",NULL,NULL);
  7609. #ifdef HEIMDAL
  7610.         code = -1;
  7611. #else /* HEIMDAL */
  7612.         code = krb5_string_to_deltat(numstr, &rlife);
  7613. #endif /* HEIMDAL */
  7614.         if (code != 0 || rlife == 0) {
  7615.             printf("Bad renewable time value %s\r\n", numstr);
  7616.             errflg++;
  7617.         }
  7618. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7619.         krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
  7620. #endif
  7621.     }
  7622.     if ( init->renew ) {
  7623.         /* renew the ticket */
  7624.         options |= KDC_OPT_RENEW;
  7625.     }
  7626.  
  7627.     if ( init->validate ) {
  7628.         /* validate the ticket */
  7629.         options |= KDC_OPT_VALIDATE;
  7630.     }
  7631.     if ( init->proxiable ) {
  7632.         options |= KDC_OPT_PROXIABLE;
  7633. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7634.         krb5_get_init_creds_opt_set_proxiable(&opts, 1);
  7635. #endif
  7636.     }
  7637.     if ( init->forwardable ) {
  7638.         options |= KDC_OPT_FORWARDABLE;
  7639. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7640.         krb5_get_init_creds_opt_set_forwardable(&opts, 1);
  7641. #endif
  7642.     }
  7643. #ifndef NO_KEYTAB
  7644.     if (  ) {
  7645.         use_keytab = 1;
  7646.     }
  7647.     if (  ) {
  7648.         if (keytab == NULL && keytab_name != NULL) {
  7649.             code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
  7650.             if (code != 0) {
  7651.                 debug(F111,"krb5_init resolving keytab",
  7652.                          keytab_name,code);
  7653.                 errflg++;
  7654.             }
  7655.         }
  7656.     }
  7657. #endif /* NO_KEYTAB */
  7658.     if ( init->lifetime ) {
  7659.         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->lifetime),"m",NULL,NULL);
  7660. #ifdef HEIMDAL
  7661.         code = -1;
  7662. #else /* HEIMDAL */
  7663.         code = krb5_string_to_deltat(numstr, &lifetime);
  7664. #endif /* HEIMDAL */
  7665.         if (code != 0 || lifetime == 0) {
  7666.             printf("Bad lifetime value %s\r\n", numstr);
  7667.             errflg++;
  7668.         }
  7669. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7670.         krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
  7671. #endif
  7672.     }
  7673.     if ( init->postdate ) {
  7674.         /* Convert cmdate() to a time_t value */
  7675.         struct tm * time_tm;
  7676.         struct tm * cmdate2tm(char *,int);
  7677.         time_tm = cmdate2tm(init->postdate,0);
  7678.         if ( time_tm )
  7679.             starttime = (krb5_timestamp) mktime(time_tm);
  7680.  
  7681.         if (code != 0 || starttime == 0 || starttime == -1) {
  7682.             krb5_deltat ktmp;
  7683. #ifdef HEIMDAL
  7684.             code = -1;
  7685. #else /* HEIMDAL */
  7686.             code = krb5_string_to_deltat(init->postdate, &ktmp);
  7687. #endif /* HEIMDAL */
  7688.             if (code == 0 && ktmp != 0) {
  7689.                 starttime = now + ktmp;
  7690.                 options |= KDC_OPT_POSTDATED;
  7691.             } else {
  7692.                 printf("Bad postdate start time value %s\r\n",
  7693.                         init->postdate);
  7694.                 errflg++;
  7695.             }
  7696.         } else {
  7697.             options |= KDC_OPT_POSTDATED;
  7698.         }
  7699.     }
  7700.  
  7701.     debug(F110,"krb5_init searching for ccache",op->cache,0);
  7702.  
  7703.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  7704.     if (code != 0) {
  7705.         com_err("krb5_kinit",code,"while getting default ccache");
  7706.         goto exit_k5_init;
  7707.     }
  7708.  
  7709.     /* This is our realm unless it is changed */
  7710.     ckstrncpy(realm,init->realm ? init->realm : krb5_d_realm, 256);
  7711.  
  7712. #ifdef BETATEST
  7713.     /* This code is going to take the realm and attempt to correct */
  7714.     /* the case.                                                   */
  7715.     {
  7716.         profile_t profile;
  7717.  
  7718.         code = krb5_get_profile(kcontext, &profile);
  7719.         if ( !code ) {
  7720.             const char  *names[4];
  7721.             char ** realms;
  7722.             int found = 0;
  7723.  
  7724.             names[0] = "realms";
  7725.             names[1] = NULL;
  7726.  
  7727.             code = profile_get_subsection_names(profile,names,&realms);
  7728.             if ( code == 0 ) {
  7729.                 int i=0;
  7730.                 while ( realms[i] ) {
  7731.                     if (ckstrcmp(realm,realms[i],-1,0) == 0) {
  7732.                         strcpy(realm,realms[i]);
  7733.                         found = 1;
  7734.                         break;
  7735.                     }
  7736.                     i++;
  7737.                 }
  7738.             }
  7739.  
  7740. #ifdef CK_DNS_SRV
  7741.             if ( !found ) {
  7742.                 char * dns_realm = NULL;
  7743.  
  7744.                 /* We did not find the realm in the profile so let's try DNS */
  7745.                 locate_txt_rr("_kerberos",realm,&dns_realm);
  7746.                 if ( dns_realm &&
  7747.                      ckstrcmp(realm,dns_realm,-1,0) == 0 &&
  7748.                      ckstrcmp(realm,dns_realm,-1,1) != 0
  7749.                      ) {
  7750.                     ckstrncpy(realm,dns_realm,256);
  7751.                     free(dns_realm);
  7752.                 }
  7753.             }
  7754. #endif /* CK_DNS_SRV */
  7755.         }
  7756.  
  7757.         if (init->realm &&
  7758.              ckstrcmp(realm,init->realm,-1,0) == 0 &&
  7759.              ckstrcmp(realm,init->realm,-1,1) != 0)
  7760.             strcpy(init->realm,realm);
  7761.         if (ckstrcmp(realm,krb5_d_realm,-1,0) == 0 &&
  7762.              ckstrcmp(realm,krb5_d_realm,-1,1) != 0)
  7763.             strcpy(krb5_d_realm,realm);
  7764.     }
  7765. #endif /* BETATEST */
  7766.  
  7767.     if (init->principal == NULL) {       /* No principal name specified */
  7768. #ifndef NO_KEYTAB
  7769.         if (use_keytab) {
  7770.             /* Use the default host/service name */
  7771.             code = krb5_sname_to_principal(kcontext, NULL, NULL,
  7772.                                             KRB5_NT_SRV_HST, &me);
  7773.             if (code == 0 &&
  7774.                 krb5_princ_realm(kcontext, me)->length < sizeof(realm))
  7775.             {
  7776.                 /* Save the realm */
  7777.                 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  7778.                         krb5_princ_realm(kcontext, me)->length); /* safe */
  7779.                 realm[krb5_princ_realm(kcontext, me)->length]='\0';
  7780.             } else {
  7781.                 com_err("krb5_kinit",
  7782.                         code,
  7783.                         "when creating default server principal name");
  7784.                 goto exit_k5_init;
  7785.             }
  7786.         } else
  7787. #endif /* NO_KEYTAB */
  7788.         {
  7789.             int len;
  7790.             char * name;
  7791.  
  7792.             /* Get default principal from cache if one exists */
  7793.             code = krb5_cc_get_principal(kcontext, ccache, &me);
  7794. #ifdef HEIMDAL
  7795.             name = me->realm;
  7796.             len = strlen(name);
  7797. #else /* HEIMDAL */
  7798.             len = krb5_princ_realm(kcontext, me)->length;
  7799.             name = krb5_princ_realm(kcontext, me)->data;
  7800. #endif /* HEIMDAL */
  7801.             if (code == 0 && len < sizeof(realm))
  7802.             {
  7803.                 /* Save the realm */
  7804.                 memcpy(realm,name,len); /* safe */
  7805.                 realm[len]='\0';
  7806.             } else {
  7807. #ifdef HAVE_PWD_H
  7808.                 /* Else search passwd file for client */
  7809.  
  7810.                 pw = getpwuid((int) getuid());
  7811.                 if (pw) {
  7812.                     char princ_realm[256];
  7813.                     if ( (strlen(pw->pw_name) + strlen(realm) + 1) > 255 )
  7814.                         goto exit_k5_init;
  7815.  
  7816.                     ckstrncpy(principal,pw->pw_name,256);
  7817.                     ckstrncpy(princ_realm,pw->pw_name,256);
  7818.                     ckstrncat(princ_realm,"@",256);
  7819.                     ckstrncat(princ_realm,realm,256);
  7820.  
  7821.                     if ((code = krb5_parse_name(kcontext,princ_realm,&me))) {
  7822.                         krb5_errno = code;
  7823.                         com_err("krb5_kinit",code,"when parsing name",
  7824.                                   princ_realm);
  7825.                         goto exit_k5_init;
  7826.                     }
  7827.                 } else {
  7828.                     printf(
  7829.                         "Unable to identify user from password file\r\n");
  7830.                     goto exit_k5_init;
  7831.                 }
  7832. #else /* HAVE_PWD_H */
  7833.                 printf("Unable to identify user\r\n");
  7834.                 goto exit_k5_init;
  7835. #endif /* HAVE_PWD_H */
  7836.             }
  7837.         }
  7838.  
  7839. #ifdef HEIMDAL
  7840.         len = me->name.name_string.len;
  7841.         name = *me->name.name_string.val;
  7842. #else /* HEIMDAL */
  7843.         len = krb5_princ_name(kcontext, me)->length;
  7844.         name = krb5_princ_name(kcontext, me)->data;
  7845. #endif /* HEIMDAL */
  7846.         if ( len < sizeof(principal) ) {
  7847.             memcpy(principal,name,len);     /* safe */
  7848.             principal[len]='\0';
  7849.         }
  7850.     } /* Use specified name */
  7851.     else {
  7852.         char princ_realm[256];
  7853.         if ( (strlen(init->principal) +
  7854.               (init->instance ? strlen(init->instance)+1 : 0) +
  7855.               strlen(realm)
  7856.               + 2) > 255 )
  7857.              goto exit_k5_init;
  7858.  
  7859.         ckstrncpy(principal,init->principal,256);
  7860.         ckstrncpy(princ_realm,init->principal,256);
  7861.         if (init->instance) {
  7862.             ckstrncat(princ_realm,"/",256);
  7863.             ckstrncat(princ_realm,init->instance,256);
  7864.         }
  7865.         if (realm[0]) {
  7866.           ckstrncat(princ_realm,"@",256);
  7867.           ckstrncat(princ_realm,realm,256);
  7868.         }
  7869.         if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
  7870.             com_err("krb5_kinit",code,"when parsing name",princ_realm);
  7871.             goto exit_k5_init;
  7872.         }
  7873.     }
  7874.  
  7875.     if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
  7876.         com_err("krb5_kinit",code,"when unparsing name");
  7877.         goto exit_k5_init;
  7878.     }
  7879.     debug(F110,"krb5_init client_name",client_name,0);
  7880.  
  7881.  
  7882.     memset((char *)&my_creds, 0, sizeof(my_creds));
  7883.     my_creds.client = me;
  7884.  
  7885.     if (init->service == NULL) {
  7886.         if ((code =
  7887.              krb5_build_principal_ext(kcontext,
  7888.                                       &server,
  7889.                                       strlen(realm),realm,
  7890.                                       tgtname.length, tgtname.data,
  7891.                                       strlen(realm),realm,
  7892.                                       0))) {
  7893.             com_err("krb5_kinit",code,"while building server name");
  7894.             goto exit_k5_init;
  7895.         }
  7896.     } else {
  7897.         if (code = krb5_parse_name(kcontext, init->service, &server)) {
  7898.             com_err("krb5_kinit",code,"while parsing service name",
  7899.                     init->service);
  7900.             goto exit_k5_init;
  7901.         }
  7902.     }
  7903.  
  7904.     my_creds.server = server;
  7905.  
  7906.     if (options & KDC_OPT_POSTDATED) {
  7907.         my_creds.times.starttime = starttime;
  7908.         my_creds.times.endtime = starttime + lifetime;
  7909.     } else {
  7910.         my_creds.times.starttime = 0;   /* start timer when request
  7911.                                            gets to KDC */
  7912.         my_creds.times.endtime = now + lifetime;
  7913.     }
  7914.     if (options & KDC_OPT_RENEWABLE) {
  7915.         my_creds.times.renew_till = now + rlife;
  7916.     } else
  7917.         my_creds.times.renew_till = 0;
  7918.  
  7919.     if (options & KDC_OPT_VALIDATE) {
  7920.         krb5_data outbuf;
  7921.  
  7922. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7923.         code = krb5_get_validated_creds(kcontext,
  7924.                                         &my_creds, me, ccache, init->service);
  7925.         if ( code == -1 )
  7926. #endif
  7927.         {
  7928. #ifdef HEIMDAL
  7929.             printf("?validate not implemented\r\n");
  7930.             code = -1;
  7931.             goto exit_k5_init;
  7932. #else /* HEIMDAL */
  7933.             code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
  7934. #endif /* HEIMDAL */
  7935.         }
  7936.         if (code) {
  7937.             com_err("krb5_kinit",code,"validating tgt");
  7938.             goto exit_k5_init;
  7939.         }
  7940.         /* should be done... */
  7941.         goto exit_k5_init;
  7942.     }
  7943.  
  7944.     if (options & KDC_OPT_RENEW) {
  7945.         krb5_data outbuf;
  7946.  
  7947. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7948.         code = krb5_get_renewed_creds(kcontext,
  7949.                                       &my_creds, me, ccache, init->service);
  7950.         if ( code == -1 )
  7951. #endif
  7952.         {
  7953. #ifdef HEIMDAL
  7954.             printf("?renew not implemented\r\n");
  7955.             code = -1;
  7956.             goto exit_k5_init;
  7957. #else /* HEIMDAL */
  7958.             code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
  7959. #endif /* HEIMDAL */
  7960.         }
  7961.         if (code) {
  7962.             com_err("krb5_kinit",code,"while renewing tgt");
  7963.             goto exit_k5_init;
  7964.         }
  7965.         /* should be done... */
  7966.         goto store_cred;
  7967.     }
  7968.  
  7969. #ifndef HEIMDAL
  7970.     if ( init->addrs && !init->no_addresses ) {
  7971.         /* construct an array of krb5_address structs to pass to get_in_tkt */
  7972.         /* include both the local ip addresses as well as any other that    */
  7973.         /* are specified.                                                   */
  7974.         unsigned long ipaddr;
  7975.  
  7976.         for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
  7977.             if ( init->addrs[addr_count] == NULL )
  7978.                 break;
  7979.  
  7980.         if (addr_count > 0) {
  7981.             krb5_address ** local_addrs=NULL;
  7982.             krb5_os_localaddr(kcontext, &local_addrs);
  7983.             i = 0;
  7984.             while ( local_addrs[i] )
  7985.                 i++;
  7986.             addr_count += i;
  7987.  
  7988.             addrs = (krb5_address **)
  7989.               malloc((addr_count+1) * sizeof(krb5_address *));
  7990.             if ( !addrs ) {
  7991.                 krb5_free_addresses(kcontext, local_addrs);
  7992.                 goto exit_k5_init;
  7993.             }
  7994.             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
  7995.             i = 0;
  7996.             while ( local_addrs[i] ) {
  7997.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  7998.                 if (addrs[i] == NULL) {
  7999.                     krb5_free_addresses(kcontext, local_addrs);
  8000.                     goto exit_k5_init;
  8001.                 }
  8002.  
  8003.                 addrs[i]->magic = local_addrs[i]->magic;
  8004.                 addrs[i]->addrtype = local_addrs[i]->addrtype;
  8005.                 addrs[i]->length = local_addrs[i]->length;
  8006.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  8007.                 if (!addrs[i]->contents) {
  8008.                     krb5_free_addresses(kcontext, local_addrs);
  8009.                     goto exit_k5_init;
  8010.                 }
  8011.  
  8012.                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
  8013.                         local_addrs[i]->length);        /* safe */
  8014.                 i++;
  8015.             }
  8016.             krb5_free_addresses(kcontext, local_addrs);
  8017.  
  8018.             for ( j=0;i<addr_count;i++,j++ ) {
  8019.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  8020.                 if (addrs[i] == NULL)
  8021.                     goto exit_k5_init;
  8022.  
  8023.                 addrs[i]->magic = KV5M_ADDRESS;
  8024.                 addrs[i]->addrtype = AF_INET;
  8025.                 addrs[i]->length = 4;
  8026.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  8027.                 if (!addrs[i]->contents)
  8028.                     goto exit_k5_init;
  8029.  
  8030.                 ipaddr = inet_addr(init->addrs[j]);
  8031.                 memcpy(addrs[i]->contents,&ipaddr,4);   /* safe */
  8032.             }
  8033. #ifdef KRB5_HAVE_GET_INIT_CREDS
  8034.             krb5_get_init_creds_opt_set_address_list(&opts,addrs);
  8035. #endif
  8036.         }
  8037.      }
  8038. #endif /* !HEIMDAL */
  8039. #ifdef KRB5_HAVE_GET_INIT_CREDS
  8040.     if ( init->no_addresses )
  8041.         krb5_get_init_creds_opt_set_address_list(&opts,NULL);
  8042. #endif
  8043.  
  8044. #ifndef NO_KEYTAB
  8045.     if (!use_keytab)
  8046. #endif
  8047.     {
  8048.         if ( init->password ) {
  8049.             pwsize = strlen(init->password);
  8050.             if ( pwsize )
  8051.                 password = init->password;
  8052.         } else if (init->getk4 && k4_init) {
  8053.             /* When we are requesting that K4 tickets be automatically */
  8054.             /* acquired when K5 tickets are acquired, we must get the  */
  8055.             /* password up front.                                      */
  8056.             char prmpt[256];
  8057.             extern char * k5prprompt;
  8058.             extern char * k5pwprompt;
  8059.             int ok = 0;
  8060.  
  8061.             if ( k5pwprompt && k5pwprompt[0] &&
  8062.                  (strlen(k5pwprompt) + strlen(principal) +
  8063.                   strlen(realm) - 4) < sizeof(prmpt)) {
  8064.                 sprintf(prmpt,k5pwprompt,principal,realm);
  8065.             } else
  8066.                 ckmakxmsg(prmpt,sizeof(prmpt),
  8067.                            k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  8068.                            "Kerberos 5 Password for ",
  8069.                            principal,"@",realm,": ",
  8070.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL
  8071.                            );
  8072.             ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
  8073.             if ( ok )
  8074.                 password = passwd;
  8075.  
  8076.             if ( k4_init->password == NULL )
  8077.                 makestr(&k4_init->password,passwd);
  8078.         }
  8079. #ifdef KRB5_HAVE_GET_INIT_CREDS
  8080.         debug(F100,"krb5_init calling krb5_get_init_creds_password()","",0);
  8081. #ifdef OS2
  8082.         if ( is_NRL_KRB5() )
  8083.             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
  8084.                                                  password,
  8085.                                                  (void *)ck_NRL_krb5_prompter,
  8086.                                                  NULL,
  8087.                                                  starttime, init->service,
  8088.                                                  &opts);
  8089.         else
  8090. #endif /* OS2 */
  8091.             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
  8092.                                                  password,
  8093.                                                  ck_krb5_prompter,
  8094.                                                  NULL,
  8095.                                                  starttime, init->service,
  8096.                                                  &opts);
  8097.         debug(F111,"krb5_init","krb5_get_init_creds_password()",code);
  8098.  
  8099.         if ( code == -1 )
  8100.         {
  8101.             if (!password) {
  8102.                 char prmpt[256];
  8103.                 int ok;
  8104.  
  8105.                 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
  8106.                           client_name,": ",NULL);
  8107.                 ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,
  8108.                 DEFAULT_UQ_TIMEOUT);
  8109.                 if ( ok )
  8110.                     password = passwd;
  8111.                 else {
  8112.                     code = -2;
  8113.                     goto exit_k5_init;
  8114.                 }
  8115.             }
  8116.  
  8117.             if ( !password ) 
  8118.                 password = "";
  8119.             code = krb5_get_in_tkt_with_password(kcontext, options,
  8120. #ifdef HEIMDAL
  8121.                                                   NULL,
  8122. #else /* HEIMDAL */
  8123.                                             init->no_addresses ? NULL :addrs,
  8124. #endif /* HEIMDAL */
  8125.                                                   NULL, NULL,
  8126.                                                   password,
  8127.                                                   NULL, &my_creds, NULL);
  8128.             if ( code )
  8129.                 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
  8130.         }
  8131. #else /* KRB5_HAVE_GET_INIT_CREDS */
  8132.         if (!password) {
  8133.             char prmpt[256];
  8134.             int ok;
  8135.  
  8136.             ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
  8137.                       client_name,": ",NULL);
  8138.             ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
  8139.             if ( ok )
  8140.                 password = passwd;
  8141.             else {
  8142.                 code = -2;
  8143.                 goto exit_k5_init;
  8144.             }
  8145.         }
  8146.         if ( !password ) 
  8147.             password = "";
  8148.         code = krb5_get_in_tkt_with_password(kcontext, options,
  8149. #ifdef HEIMDAL
  8150.                                               NULL,
  8151. #else /* HEIMDAL */
  8152.                                             init->no_addresses ? NULL :addrs,
  8153. #endif /* HEIMDAL */
  8154.                                               NULL, NULL,
  8155.                                               password,
  8156.                                               NULL, &my_creds, NULL);
  8157.         if ( code )
  8158.             debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
  8159. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  8160.  
  8161.         if ( init->password && pwsize > 0 )
  8162.             memset(init->password, 0, pwsize);
  8163.         memset(passwd,0,80);
  8164.     }
  8165. #ifndef NO_KEYTAB
  8166.     else {
  8167. #ifdef KRB5_HAVE_GET_INIT_CREDS
  8168.         code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
  8169.                                            starttime, init->service,
  8170.                                            &opts);
  8171. #ifdef OS2
  8172.         if ( code == -1)
  8173.             code = krb5_get_in_tkt_with_keytab(kcontext, options,
  8174.                                            init->no_addresses ? NULL :addrs,
  8175.                                                 NULL, NULL, keytab, NULL,
  8176.                                                 &my_creds, 0);
  8177. #endif /* OS2 */
  8178. #else /* KRB5_HAVE_GET_INIT_CREDS */
  8179.         code = krb5_get_in_tkt_with_keytab(kcontext, options,
  8180. #ifdef HEIMDAL
  8181.                                                   NULL,
  8182. #else /* HEIMDAL */
  8183.                                             init->no_addresses ? NULL :addrs,
  8184. #endif /* HEIMDAL */
  8185.                                             NULL, NULL, keytab, NULL,
  8186.                                             &my_creds, 0);
  8187. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  8188.     }
  8189. #endif
  8190.  
  8191.     if (code) {
  8192.         switch (code) {
  8193.         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
  8194.             printf("Password incorrect\r\n");
  8195.             goto exit_k5_init;
  8196.         case KRB5KRB_AP_ERR_V4_REPLY:
  8197.             if (init->getk4 && k4_init) {
  8198.                 printf("Kerberos 5 Tickets not support by server.  ");
  8199.                 printf("A version 4 Ticket will be requested.\r\n");
  8200.             }
  8201.             goto exit_k5_init;
  8202.         default:
  8203.             goto exit_k5_init;
  8204.         }
  8205.     }
  8206.  
  8207.   store_cred:
  8208.     debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
  8209.  
  8210.     code = krb5_cc_initialize (kcontext, ccache, me);
  8211.     if ( code == KRB5_CC_BADNAME ) {
  8212.         /* This is a really ugly hack that should not have to be here.
  8213.          * krb5_cc_initialize should not fail with an error if the
  8214.          * cache already exists.  The reason the problem is occuring
  8215.          * is that the krb5 library is no longer calling cc_destroy()
  8216.          * when cc_initialize() is called and the CCAPI implementation
  8217.          * on Windows has not yet been corrected to handle it.  To
  8218.          * ensure that K95 will continue to work with both we will call
  8219.          * cc_destroy() if the cc_initialize() call fails with a BADNAME
  8220.          * error.  If the cc_destroy() is successful, we will try again.
  8221.          */
  8222.  
  8223.         debug(F100,"krb5_init calling krb5_cc_destroy()","",0);
  8224.         code = krb5_cc_destroy (kcontext, ccache);
  8225.         if ( !code ) {
  8226.             debug(F100,"krb5_init calling k5_get_ccache()","",0);
  8227.             code = k5_get_ccache(kcontext,&ccache,op->cache);
  8228.             debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
  8229.             code = krb5_cc_initialize (kcontext, ccache, me);
  8230.         } else
  8231.             code = KRB5_CC_BADNAME;
  8232.     }
  8233.     if (code) {
  8234.         com_err("krb5_kinit",code,"when initializing cache",op->cache);
  8235.         goto exit_k5_init;
  8236.     }
  8237.  
  8238.     debug(F100,"krb5_init calling krb5_cc_store_cred()","",0);
  8239.     code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
  8240.     if (code) {
  8241.         com_err("krb5_kinit",code,"while storing credentials");
  8242.         goto exit_k5_init;
  8243.     }
  8244.  
  8245.     if ( init->getk4 && 
  8246. #ifdef KRB524_CONV
  8247.          !try_convert524(kcontext,me,ccache) && 
  8248. #endif /* KRB524_CONV */
  8249.          k4_init ) {
  8250.         int k4rc = ck_krb4_initTGT(op,k4_init);
  8251.         if (k4rc < 0)
  8252.             code = -3;
  8253.     }
  8254.  
  8255. exit_k5_init:
  8256.     debug(F100,"krb5_init exit_k5_init","",0);
  8257.  
  8258. #ifndef HEIMDAL
  8259.     /* Free krb5_address structures if we created them */
  8260.     if ( addrs ) {
  8261.         for ( i=0;i<addr_count;i++ ) {
  8262.             if ( addrs[i] ) {
  8263.                 if ( addrs[i]->contents )
  8264.                     free(addrs[i]->contents);
  8265.                 free(addrs[i]);
  8266.             }
  8267.         }
  8268.     }
  8269. #endif /* HEIMDAL */
  8270.  
  8271.  
  8272.     krb5_errno = code;
  8273.     makestr(&krb5_errmsg,krb5_errno ? error_message(krb5_errno) : "OK");
  8274.  
  8275.     if (client_name)
  8276.         krb5_free_unparsed_name(kcontext, client_name);
  8277.  
  8278.     /* my_creds is pointing at server */
  8279.     debug(F100,"krb5_init calling krb5_free_principal()","",0);
  8280.     krb5_free_principal(kcontext, server);
  8281.     debug(F100,"krb5_init calling krb5_cc_close()","",0);
  8282.     krb5_cc_close(kcontext,ccache);
  8283.     debug(F100,"krb5_init calling krb5_free_context()","",0);
  8284.     krb5_free_context(kcontext);
  8285.  
  8286.     if (code != -2)
  8287.         printf("Result from realm %s: %s\r\n",realm,
  8288.                 code==-3?"Unable to retrieve Kerberos IV credentials":
  8289.                 code?error_message(code):"OK");
  8290.     return(code?-1:0);
  8291. }
  8292.  
  8293. #ifndef HEIMDAL
  8294. #define VALIDATE 0
  8295. #define RENEW 1
  8296.  
  8297. /* stripped down version of krb5_mk_req */
  8298. static krb5_error_code
  8299. #ifdef CK_ANSIC
  8300. krb5_validate_tgt( krb5_context context,
  8301.                    krb5_ccache ccache,
  8302.                    krb5_principal     server, /* tgtname */
  8303.                    krb5_data *outbuf )
  8304. #else
  8305. krb5_validate_tgt(context, ccache, server, outbuf)
  8306.      krb5_context context;
  8307.      krb5_ccache ccache;
  8308.      krb5_principal     server; /* tgtname */
  8309.      krb5_data *outbuf;
  8310. #endif
  8311. {
  8312.     return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
  8313. }
  8314.  
  8315. /* stripped down version of krb5_mk_req */
  8316. static krb5_error_code
  8317. #ifdef CK_ANSIC
  8318. krb5_renew_tgt(krb5_context context,
  8319.                 krb5_ccache ccache,
  8320.                 krb5_principal    server, /* tgtname */
  8321.                 krb5_data *outbuf)
  8322. #else
  8323. krb5_renew_tgt(context, ccache, server, outbuf)
  8324.      krb5_context context;
  8325.      krb5_ccache ccache;
  8326.      krb5_principal       server; /* tgtname */
  8327.      krb5_data *outbuf;
  8328. #endif
  8329. {
  8330.     return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
  8331. }
  8332.  
  8333.  
  8334. /* stripped down version of krb5_mk_req */
  8335. static krb5_error_code
  8336. #ifdef CK_ANSIC
  8337. krb5_tgt_gen(krb5_context context,
  8338.               krb5_ccache ccache,
  8339.               krb5_principal      server, /* tgtname */
  8340.               krb5_data *outbuf,
  8341.               int opt)
  8342. #else
  8343. krb5_tgt_gen(context, ccache, server, outbuf, opt)
  8344.      krb5_context context;
  8345.      krb5_ccache ccache;
  8346.      krb5_principal       server; /* tgtname */
  8347.      krb5_data *outbuf;
  8348.      int opt;
  8349. #endif
  8350. {
  8351.     krb5_error_code       retval;
  8352.     krb5_creds          * credsp;
  8353.     krb5_creds            creds;
  8354.  
  8355.     /* obtain ticket & session key */
  8356.     memset((char *)&creds, 0, sizeof(creds));
  8357.     if ((retval = krb5_copy_principal(context, server, &creds.server)))
  8358.         goto cleanup;
  8359.  
  8360.     if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
  8361.         goto cleanup_creds;
  8362.  
  8363.     if (opt == VALIDATE) {
  8364.         if ((retval = krb5_get_credentials_validate(context, 0,
  8365.                                                     ccache, &creds, &credsp)))
  8366.           goto cleanup_creds;
  8367.     } else {
  8368.         if ((retval = krb5_get_credentials_renew(context, 0,
  8369.                                                  ccache, &creds, &credsp)))
  8370.           goto cleanup_creds;
  8371.     }
  8372.  
  8373.     /* we don't actually need to do the mk_req, just get the creds. */
  8374. cleanup_creds:
  8375.     krb5_free_cred_contents(context, &creds);
  8376.  
  8377. cleanup:
  8378.  
  8379.     return retval;
  8380. }
  8381. #endif /* HEIMDAL */
  8382. #endif /* KINIT */
  8383. #ifdef KDESTROY
  8384. int
  8385. #ifdef CK_ANSIC
  8386. ck_krb5_destroy(struct krb_op_data * op)
  8387. #else
  8388. ck_krb5_destroy(op) struct krb_op_data * op;
  8389. #endif
  8390. {
  8391.     krb5_context kcontext;
  8392.     krb5_error_code retval;
  8393.     int c;
  8394.     krb5_ccache ccache = NULL;
  8395.     char *cache_name = NULL;
  8396.     int code;
  8397.     int errflg=0;
  8398.     int quiet = 0;
  8399.  
  8400.     if ( !ck_krb5_is_installed() )
  8401.         return(-1);
  8402.  
  8403.     code = krb5_init_context(&kcontext);
  8404.     if (code) {
  8405.         debug(F101,"ck_krb5_destroy while initializing krb5","",code);
  8406.         krb5_errno = code;
  8407.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8408.         return(-1);
  8409.     }
  8410.  
  8411.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  8412.     if (code != 0) {
  8413.         debug(F101,"ck_krb5_destroy while getting ccache",
  8414.                "",code);
  8415.         krb5_free_context(kcontext);
  8416.         krb5_errno = code;
  8417.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8418.         return(-1);
  8419.     }
  8420.  
  8421.     code = krb5_cc_destroy (kcontext, ccache);
  8422.     if (code != 0) {
  8423.         debug(F101,"ck_krb5_destroy while destroying cache","",code);
  8424.         if ( code == KRB5_FCC_NOFILE )
  8425.             printf("No ticket cache to destroy.\r\n");
  8426.         else
  8427.             printf("Ticket cache NOT destroyed!\r\n");
  8428.         krb5_cc_close(kcontext,ccache);
  8429.         krb5_free_context(kcontext);
  8430.         krb5_errno = code;
  8431.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8432.         return(-1);
  8433.     }
  8434.  
  8435.     printf("Tickets destroyed.\r\n");
  8436.     /* Do not call krb5_cc_close() because cache has been destroyed */
  8437.     krb5_free_context(kcontext);
  8438.     krb5_errno = 0;
  8439.     makestr(&krb5_errmsg,"OK");
  8440.     return (0);
  8441. }
  8442. #else /* KDESTROY */
  8443. #ifdef KRB5
  8444. int
  8445. #ifdef CK_ANSIC
  8446. ck_krb5_destroy(struct krb_op_data * op)
  8447. #else
  8448. ck_krb5_destroy(op) struct krb_op_data * op;
  8449. #endif
  8450. {
  8451.     printf("?Not implemented.\r\n");
  8452.     return(-1);
  8453. }
  8454. #endif /* KRB5 */
  8455. #endif /* KDESTROY */
  8456. #ifndef KLIST
  8457. #ifdef KRB5
  8458. int
  8459. #ifdef CK_ANSIC
  8460. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  8461. #else
  8462. ck_krb5_list_creds(op,lc)
  8463.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  8464. #endif
  8465. {
  8466.     printf("?Not implemented.\r\n");
  8467.     return(-1);
  8468. }
  8469. #endif /* KRB5 */
  8470. #else /* KLIST */
  8471. static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
  8472. static int show_etype = 0, show_addr = 0;
  8473. static char *defname;
  8474. static char *progname;
  8475. static krb5_int32 now;
  8476. static int timestamp_width;
  8477.  
  8478. _PROTOTYP(static char * etype_string, (krb5_enctype ));
  8479. _PROTOTYP(static void show_credential,(krb5_context,krb5_creds *));
  8480. _PROTOTYP(static int do_ccache, (krb5_context,char *));
  8481. _PROTOTYP(static int do_keytab, (krb5_context,char *));
  8482. _PROTOTYP(static void printtime, (time_t));
  8483. _PROTOTYP(static void fillit, (int, int));
  8484.  
  8485. #define DEFAULT 0
  8486. #define CCACHE 1
  8487. #define KEYTAB 2
  8488.  
  8489. int
  8490. #ifdef CK_ANSIC
  8491. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  8492. #else
  8493. ck_krb5_list_creds(op,lc)
  8494.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  8495. #endif
  8496. {
  8497.     krb5_context kcontext;
  8498.     krb5_error_code retval;
  8499.     int code;
  8500.     char *name = op->cache;
  8501.     int mode;
  8502.  
  8503.     if ( !ck_krb5_is_installed() )
  8504.         return(-1);
  8505.  
  8506.     code = krb5_init_context(&kcontext);
  8507.     if (code) {
  8508.         debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
  8509.         krb5_errno = code;
  8510.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8511.         return(-1);
  8512.     }
  8513.  
  8514.     name = op->cache;
  8515.     mode = DEFAULT;
  8516.     show_flags = 0;
  8517.     show_time = 0;
  8518.     status_only = 0;
  8519.     show_keys = 0;
  8520.     show_etype = 0;
  8521.     show_addr = 0;
  8522.  
  8523.     show_flags = lc->flags;
  8524.     show_etype = lc->encryption;
  8525.     show_addr  = lc->addr;
  8526.     show_time = 1;
  8527.     show_keys = 1;
  8528.     mode = CCACHE;
  8529.  
  8530.     if ((code = krb5_timeofday(kcontext, &now))) {
  8531.         if (!status_only)
  8532.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  8533.                    "",code);
  8534.         krb5_free_context(kcontext);
  8535.         krb5_errno = code;
  8536.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8537.         return(-1);
  8538.     }
  8539.     else {
  8540.         char tmp[BUFSIZ];
  8541.  
  8542.         if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
  8543.             !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
  8544.             timestamp_width = (int) strlen(tmp);
  8545.         else
  8546.             timestamp_width = 15;
  8547.     }
  8548.  
  8549.     if (mode == DEFAULT || mode == CCACHE)
  8550.          retval = do_ccache(kcontext,name);
  8551.     else
  8552.          retval = do_keytab(kcontext,name);
  8553.     krb5_free_context(kcontext);
  8554.     return(retval);
  8555. }
  8556.  
  8557. static int
  8558. #ifdef CK_ANSIC
  8559. do_keytab(krb5_context kcontext, char * name)
  8560. #else
  8561. do_keytab(kcontext,name) krb5_context kcontext; char * name;
  8562. #endif
  8563. {
  8564.     krb5_keytab kt;
  8565.     krb5_keytab_entry entry;
  8566.     krb5_kt_cursor cursor;
  8567.     char buf[BUFSIZ]; /* hopefully large enough for any type */
  8568.     char *pname;
  8569.     int code = 0;
  8570.  
  8571.     if (name == NULL) {
  8572.         if ((code = krb5_kt_default(kcontext, &kt))) {
  8573.             debug(F101,"ck_krb5_list_creds while getting default keytab",
  8574.                    "",code);
  8575.             krb5_errno = code;
  8576.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8577.             return(-1);
  8578.         }
  8579.     } else {
  8580.         if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
  8581.             debug(F111,"ck_krb5_list_creds while resolving keytab",
  8582.                      name,code);
  8583.             krb5_errno = code;
  8584.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8585.             return(-1);
  8586.         }
  8587.     }
  8588.  
  8589.     if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
  8590.         debug(F101,"ck_krb5_list_creds while getting keytab name",
  8591.                "",code);
  8592.         krb5_errno = code;
  8593.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8594.         return(-1);
  8595.     }
  8596.  
  8597.      printf("Keytab name: %s\r\n", buf);
  8598.  
  8599.      if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
  8600.          debug(F101,"ck_krb5_list_creds while starting keytab scan",
  8601.                 "",code);
  8602.          krb5_errno = code;
  8603.          makestr(&krb5_errmsg,error_message(krb5_errno));
  8604.          return(-1);
  8605.      }
  8606.  
  8607.      if (show_time) {
  8608.           printf("KVNO Timestamp");
  8609.           fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
  8610.           printf("Principal\r\n");
  8611.           printf("---- ");
  8612.           fillit(timestamp_width, (int) '-');
  8613.           printf(" ");
  8614.           fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
  8615.           printf("\r\n");
  8616.      } else {
  8617.           printf("KVNO Principal\r\n");
  8618.           printf(
  8619. "---- --------------------------------------------------------------------\
  8620. ------\r\n");
  8621.      }
  8622.  
  8623.     while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
  8624.         if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
  8625.             debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8626.                    "",code);
  8627.             krb5_errno = code;
  8628.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8629.             return(-1);
  8630.         }
  8631.         printf("%4d ", entry.vno);
  8632.         if (show_time) {
  8633.             printtime(entry.timestamp);
  8634.             printf(" ");
  8635.         }
  8636.         printf("%s", pname);
  8637.         if (show_etype)
  8638.             printf(" (%s) " ,
  8639. #ifdef HEIMDAL
  8640.                     etype_string(entry.key.keytype)
  8641. #else /* HEIMDAL */
  8642.                     etype_string(entry.key.enctype)
  8643. #endif /* HEIMDAL */
  8644.                     );
  8645.         if (show_keys) {
  8646.             printf(" (0x");
  8647.             {
  8648.                 int i;
  8649.                 for (i = 0; i < entry.key.length; i++)
  8650.                     printf("%02x",
  8651. #ifdef HEIMDAL
  8652.                             entry.key.keyvalue[i]
  8653. #else /* HEIMDAL */
  8654.                             entry.key.contents[i]
  8655. #endif /* HEIMDAL */
  8656.                             );
  8657.             }
  8658.             printf(")");
  8659.         }
  8660.         printf("\r\n");
  8661.         krb5_free_unparsed_name(kcontext,pname);
  8662.     }
  8663.     if (code && code != KRB5_KT_END) {
  8664.         debug(F101,"ck_krb5_list_creds while scanning keytab",
  8665.                "",code);
  8666.         krb5_errno = code;
  8667.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8668.         return(-1);
  8669.     }
  8670.     if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
  8671.         debug(F101,"ck_krb5_list_creds while ending keytab scan",
  8672.                "",code);
  8673.         krb5_errno = code;
  8674.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8675.         return(-1);
  8676.     }
  8677.     krb5_errno = 0;
  8678.     makestr(&krb5_errmsg,"OK");
  8679.     return(0);
  8680. }
  8681.  
  8682. static int
  8683. #ifdef CK_ANSIC
  8684. do_ccache(krb5_context kcontext, char * cc_name)
  8685. #else
  8686. do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
  8687. #endif
  8688. {
  8689.     krb5_ccache cache = NULL;
  8690.     krb5_cc_cursor cur;
  8691.     krb5_creds creds;
  8692.     krb5_principal princ=NULL;
  8693.     krb5_flags flags=0;
  8694.     krb5_error_code code = 0;
  8695.     int exit_status = 0;
  8696.  
  8697.     if (status_only)
  8698.         /* exit_status is set back to 0 if a valid tgt is found */
  8699.         exit_status = 1;
  8700.  
  8701.     code = k5_get_ccache(kcontext,&cache,cc_name);
  8702.     if (code != 0) {
  8703.         debug(F111,"do_ccache while getting ccache",
  8704.                error_message(code),code);
  8705.         krb5_errno = code;
  8706.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8707.         return(-1);
  8708.     }
  8709.  
  8710.     flags = 0;                          /* turns off OPENCLOSE mode */
  8711.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8712.         if (code == ENOENT) {
  8713.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  8714.                    krb5_cc_get_name(kcontext, cache),code);
  8715.         } else {
  8716.             debug(F111,
  8717.                  "ck_krb5_list_creds while setting cache flags (ticket cache)",
  8718.                   krb5_cc_get_name(kcontext, cache),code);
  8719.         }
  8720.         printf("No ticket File.\r\n");
  8721.         krb5_errno = code;
  8722.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8723.         krb5_cc_close(kcontext,cache);
  8724.         return(-1);
  8725.     }
  8726.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  8727.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  8728.                "",code);
  8729.         krb5_errno = code;
  8730.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8731.         krb5_cc_close(kcontext,cache);
  8732.         return(-1);
  8733.     }
  8734.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  8735.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8736.                "",code);
  8737.         krb5_errno = code;
  8738.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8739.         krb5_cc_close(kcontext,cache);
  8740.         return(-1);
  8741.     }
  8742.     if (!status_only) {
  8743.         printf("Ticket cache:      %s:%s\r\nDefault principal: %s\r\n\r\n",
  8744.                 krb5_cc_get_type(kcontext, cache),
  8745.                 krb5_cc_get_name(kcontext, cache), defname);
  8746.         printf("Valid starting");
  8747.         fillit(timestamp_width - sizeof("Valid starting") + 3,
  8748.                (int) ' ');
  8749.         printf("Expires");
  8750.         fillit(timestamp_width - sizeof("Expires") + 3,
  8751.                (int) ' ');
  8752.         printf("Service principal\r\n");
  8753.     }
  8754.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  8755.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  8756.                "",code);
  8757.         krb5_errno = code;
  8758.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8759.         krb5_cc_close(kcontext,cache);
  8760.         return(-1);
  8761.     }
  8762.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  8763.         if (status_only) {
  8764.             if (exit_status && creds.server->length == 2 &&
  8765.                 strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
  8766.                 strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
  8767.                 strcmp((char *)creds.server->data[1].data,
  8768.                        princ->realm.data) == 0 &&
  8769.                 creds.times.endtime > now)
  8770.                 exit_status = 0;
  8771.         } else {
  8772.             show_credential(kcontext, &creds);
  8773.         }
  8774.         krb5_free_cred_contents(kcontext, &creds);
  8775.     }
  8776.     printf("\r\n");
  8777.     if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
  8778.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  8779.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  8780.                    "",code);
  8781.             krb5_errno = code;
  8782.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8783.             krb5_cc_close(kcontext,cache);
  8784.             return(-1);
  8785.         }
  8786.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  8787.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8788.             debug(F101,"ck_krb5_list_creds while closing ccache",
  8789.                    "",code);
  8790.             krb5_errno = code;
  8791.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8792.             krb5_cc_close(kcontext,cache);
  8793.             return(-1);
  8794.         }
  8795.         krb5_errno = 0;
  8796.         makestr(&krb5_errmsg,"OK");
  8797.         krb5_cc_close(kcontext,cache);
  8798.         return(0);
  8799.     } else {
  8800.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  8801.         krb5_errno = code;
  8802.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8803.         krb5_cc_close(kcontext,cache);
  8804.         return(-1);
  8805.     }
  8806.     krb5_errno = 0;
  8807.     makestr(&krb5_errmsg,"OK");
  8808.     krb5_cc_close(kcontext,cache);
  8809.     return(0);
  8810. }
  8811.  
  8812. static char *
  8813. #ifdef CK_ANSIC
  8814. #ifdef HEIMDAL
  8815. etype_string(krb5_keytype enctype)
  8816. #else /* HEIMDAL */
  8817. etype_string(krb5_enctype enctype)
  8818. #endif /* HEIMDAL */
  8819. #else
  8820. #ifdef HEIMDAL
  8821. etype_string(enctype) krb5_keytype enctype;
  8822. #else /* HEIMDAL */
  8823. etype_string(enctype) krb5_enctype enctype;
  8824. #endif /* HEIMDAL */
  8825. #endif
  8826. {
  8827.     static char buf[12];
  8828.  
  8829.     switch (enctype) {
  8830.     case ENCTYPE_NULL:
  8831.         return "NULL";
  8832.     case ENCTYPE_DES_CBC_CRC:
  8833.         return "DES-CBC-CRC";
  8834.     case ENCTYPE_DES_CBC_MD4:
  8835.         return "DES-CBC-MD4";
  8836.     case ENCTYPE_DES_CBC_MD5:
  8837.         return "DES-CBC-MD5";
  8838.     case ENCTYPE_DES_CBC_RAW:
  8839.         return "DES-CBC-RAW";
  8840.     case ENCTYPE_DES3_CBC_SHA:
  8841.         return "DES3-CBC-SHA";
  8842.     case ENCTYPE_DES3_CBC_RAW:
  8843.         return "DES3-CBC-RAW";
  8844.     case ENCTYPE_DES_HMAC_SHA1:
  8845.         return "DES-HMAC-SHA1";
  8846.     case ENCTYPE_DES3_CBC_SHA1:
  8847.         return "DES3-CBC-SHA1";
  8848.     case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
  8849.         return "AES128_CTS-HMAC-SHA1_96";
  8850.     case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
  8851.         return "AES256_CTS-HMAC-SHA1_96";
  8852.     case ENCTYPE_ARCFOUR_HMAC:
  8853.         return "RC4-HMAC-NT";
  8854.     case ENCTYPE_ARCFOUR_HMAC_EXP:
  8855.         return "RC4-HMAC-NT-EXP";
  8856.     case ENCTYPE_UNKNOWN:
  8857.         return "UNKNOWN";
  8858.     case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
  8859.         return "LOCAL-DES3-HMAC-SHA1";
  8860.     case ENCTYPE_LOCAL_RC4_MD4:
  8861.         return "LOCAL-RC4-MD4";
  8862.     default:
  8863.         ckmakmsg(buf, sizeof(buf),"etype ", ckitoa(enctype),NULL,NULL);
  8864.         return buf;
  8865.         break;
  8866.     }
  8867. }
  8868.  
  8869. static char *
  8870. #ifdef CK_ANSIC
  8871. flags_string(register krb5_creds *cred)
  8872. #else
  8873. flags_string(cred) register krb5_creds *cred;
  8874. #endif
  8875. {
  8876.     static char buf[32];
  8877.     int i = 0;
  8878.  
  8879.     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
  8880.         buf[i++] = 'F';
  8881.     if (cred->ticket_flags & TKT_FLG_FORWARDED)
  8882.         buf[i++] = 'f';
  8883.     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
  8884.         buf[i++] = 'P';
  8885.     if (cred->ticket_flags & TKT_FLG_PROXY)
  8886.         buf[i++] = 'p';
  8887.     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
  8888.         buf[i++] = 'D';
  8889.     if (cred->ticket_flags & TKT_FLG_POSTDATED)
  8890.         buf[i++] = 'd';
  8891.     if (cred->ticket_flags & TKT_FLG_INVALID)
  8892.         buf[i++] = 'i';
  8893.     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
  8894.         buf[i++] = 'R';
  8895.     if (cred->ticket_flags & TKT_FLG_INITIAL)
  8896.         buf[i++] = 'I';
  8897.     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
  8898.         buf[i++] = 'H';
  8899.     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
  8900.         buf[i++] = 'A';
  8901.     buf[i] = '\0';
  8902.     return(buf);
  8903. }
  8904.  
  8905. static char   *
  8906. #ifdef CK_ANSIC
  8907. short_date(long   *dp)
  8908. #else
  8909. short_date(dp) long   *dp;
  8910. #endif
  8911. {
  8912.     register char *cp;
  8913. #ifndef ctime
  8914.     extern char *ctime();
  8915. #endif /* ctime */
  8916.     cp = ctime(dp) + 4;
  8917.     cp[15] = '\0';
  8918.     return (cp);
  8919. }
  8920.  
  8921.  
  8922. static VOID
  8923. #ifdef CK_ANSIC
  8924. printtime(time_t tv)
  8925. #else
  8926. printtime(tv) time_t tv;
  8927. #endif
  8928. {
  8929.     char timestring[BUFSIZ];
  8930.     char format[12];
  8931.     char fill;
  8932.  
  8933.     fill = ' ';
  8934.     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
  8935.     if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
  8936.                                      timestring,
  8937.                                      timestamp_width+1,
  8938.                                      &fill)) {
  8939.         printf(format,timestring);
  8940.     }
  8941.     else {
  8942.         printf(format,short_date(&tv));
  8943.     }
  8944.  
  8945. }
  8946.  
  8947. static void
  8948. #ifdef CK_ANSIC
  8949. one_addr(krb5_address *a)
  8950. #else
  8951. one_addr(a) krb5_address *a;
  8952. #endif
  8953. {
  8954.     struct hostent *h;
  8955.     extern tcp_rdns;
  8956.  
  8957.     if ((a->addrtype == ADDRTYPE_INET) &&
  8958.         (a->length == 4)) {
  8959.         if (tcp_rdns != SET_OFF) {
  8960.             h = gethostbyaddr(a->contents, 4, AF_INET);
  8961.             if (h) {
  8962. #ifdef HADDRLIST
  8963.                 h = ck_copyhostent(h);
  8964. #endif /* HADDRLIST */
  8965.                 printf("%s (%d.%d.%d.%d)", h->h_name,
  8966.                         a->contents[0], a->contents[1],
  8967.                         a->contents[2], a->contents[3]);
  8968.             }
  8969.         }
  8970.         if (tcp_rdns == SET_OFF || !h) {
  8971.             printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
  8972.                    a->contents[2], a->contents[3]);
  8973.         }
  8974.     } else {
  8975.         printf("unknown addr type %d", a->addrtype);
  8976.     }
  8977. }
  8978.  
  8979. static VOID
  8980. #ifdef CK_ANSIC
  8981. show_credential(krb5_context kcontext, register krb5_creds * cred)
  8982. #else
  8983. show_credential(kcontext, cred)
  8984.     krb5_context          kcontext;
  8985.     register krb5_creds * cred;
  8986. #endif
  8987. {
  8988.     krb5_error_code retval=0;
  8989.     krb5_ticket *tkt=NULL;
  8990.     char *name=NULL, *sname=NULL, *flags=NULL;
  8991.     int extra_field = 0;
  8992.  
  8993.     retval = krb5_unparse_name(kcontext, cred->client, &name);
  8994.     if (retval) {
  8995.         debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
  8996.         krb5_errno = retval;
  8997.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8998.         return;
  8999.     }
  9000.     retval = krb5_unparse_name(kcontext, cred->server, &sname);
  9001.     if (retval) {
  9002.         debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
  9003.         free(name);
  9004.         krb5_errno = retval;
  9005.         makestr(&krb5_errmsg,error_message(krb5_errno));
  9006.         return;
  9007.     }
  9008.     if (!cred->times.starttime)
  9009.         cred->times.starttime = cred->times.authtime;
  9010.  
  9011.     printtime(cred->times.starttime);
  9012.     printf("  ");
  9013.  
  9014.     if ( time(0) < cred->times.endtime )
  9015.         printtime(cred->times.endtime);
  9016.     else
  9017.         printf("** expired ** ");
  9018.  
  9019.     printf("  %s\r\n", sname);
  9020.  
  9021.     if (strcmp(name, defname)) {
  9022.         printf("   for client %s", name);
  9023.         extra_field++;
  9024.     }
  9025.  
  9026.     if (cred->times.renew_till) {
  9027.         if (!extra_field)
  9028.             printf("   ");
  9029.         else
  9030.             printf(", ");
  9031.         printf("renew until ");
  9032.         printtime(cred->times.renew_till);
  9033.         extra_field += 2;
  9034.     }
  9035.  
  9036.     if (extra_field > 3) {
  9037.         printf("\r\n");
  9038.         extra_field = 0;
  9039.     }
  9040.  
  9041.     if (show_flags) {
  9042.         flags = flags_string(cred);
  9043.         if (flags && *flags) {
  9044.             if (!extra_field)
  9045.                 printf("   ");
  9046.             else
  9047.                 printf(", ");
  9048.             printf("Flags: %s", flags);
  9049.             extra_field++;
  9050.         }
  9051.     }
  9052.  
  9053.     if (extra_field > 2) {
  9054.         printf("\r\n");
  9055.         extra_field = 0;
  9056.     }
  9057.  
  9058.     if (show_etype) {
  9059.         retval = decode_krb5_ticket(&cred->ticket, &tkt);
  9060.         if (!extra_field)
  9061.             printf("   ");
  9062.         else
  9063.             printf(", ");
  9064. #ifdef HEIMDAL
  9065.         printf("Etype (skey, tkt): %s, %s ",
  9066.                etype_string(cred->session.keytype),
  9067.                etype_string(tkt->enc_part.keytype));
  9068. #else /* HEIMDAL */
  9069.         printf("Etype (skey, tkt): %s, %s ",
  9070.                etype_string(cred->keyblock.enctype),
  9071.                etype_string(tkt->enc_part.enctype));
  9072. #endif /* HEIMDAL */
  9073.         krb5_free_ticket(kcontext, tkt);
  9074.         extra_field++;
  9075.     }
  9076.  
  9077.     /* if any additional info was printed, extra_field is non-zero */
  9078.     if (extra_field)
  9079.         printf("\r\n");
  9080.  
  9081.     if ( show_addr ) {
  9082.         if (!cred->addresses || !cred->addresses[0]) {
  9083.             printf("\tAddresses: (none)\r\n");
  9084.         } else {
  9085.             int i;
  9086.             for (i=0; cred->addresses[i]; i++) {
  9087.                 if (i)
  9088.                     printf("              ");
  9089.                 else
  9090.                     printf("   Addresses: ");
  9091.                 one_addr(cred->addresses[i]);
  9092.                 printf("\r\n");
  9093.             }
  9094.         }
  9095.     }
  9096.  
  9097.     krb5_free_unparsed_name(kcontext,name);
  9098.     krb5_free_unparsed_name(kcontext,sname);
  9099.  
  9100.     krb5_errno = 0;
  9101.     makestr(&krb5_errmsg,"OK");
  9102. }
  9103.  
  9104. static VOID
  9105. #ifdef CK_ANSIC
  9106. fillit(int num, int c)
  9107. #else
  9108. fillit(num, c) int num; int c;
  9109. #endif
  9110. {
  9111.     int i;
  9112.  
  9113.     for (i=0; i<num; i++)
  9114.         printf("%c",c);
  9115. }
  9116. #endif /* KLIST */
  9117. #endif /* KRB5 */
  9118.  
  9119. #ifdef KRB4
  9120. #define KDEBUG 1
  9121. int k4debug = 0;                /* Kerberos 4 runtime debugging */
  9122.  
  9123. #ifdef KINIT
  9124. #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
  9125.  
  9126. #ifdef SNK4
  9127. /* SNK4 is a hardware authentication system used to pre-authenticate    */
  9128. /* a ticket getting ticket.  We do not support this code at the present */
  9129. /* time in Kermit.                                                      */
  9130. void
  9131. get_input(s, size, stream)
  9132. char *s;
  9133. int size;
  9134. FILE *stream;
  9135. {
  9136.     char *p;
  9137.  
  9138.     if (fgets(s, size, stream) == NULL)
  9139.         exit(1);
  9140.     if ( (p = strchr(s, '\n')) != NULL)
  9141.         *p = '\0';
  9142. }
  9143. #endif /* SNK4 */
  9144.  
  9145. #ifdef COMMENT
  9146. static char
  9147. #ifdef CK_ANSIC
  9148. hex_scan_nybble(char c)
  9149. #else
  9150. hex_scan_nybble(c) char c;
  9151. #endif
  9152. {
  9153.     if (c >= '0' && c <= '9')
  9154.         return c - '0';
  9155.     if (c >= 'A' && c <= 'F')
  9156.         return c - 'A' + 10;
  9157.     if (c >= 'a' && c <= 'f')
  9158.         return c - 'a' + 10;
  9159.     return -1;
  9160. }
  9161.  
  9162. /* returns: NULL for ok, pointer to error string for bad input */
  9163. static char*
  9164. #ifdef CK_ANSIC
  9165. hex_scan_four_bytes(char *out, char *in)
  9166. #else
  9167. hex_scan_four_bytes(out, in) char *out; char *in;
  9168. #endif
  9169. {
  9170.     int i;
  9171.     int c;
  9172.     char c1;
  9173.     for (i=0; i<8; i++) {
  9174.         if(!in[i])
  9175.             return "not enough input";
  9176.         c = hex_scan_nybble(in[i]);
  9177.         if(c<0)
  9178.             return "invalid digit";
  9179.         c1 = c;
  9180.         i++;
  9181.         if(!in[i])
  9182.             return "not enough input";
  9183.         c = hex_scan_nybble(in[i]);
  9184.         if(c<0)
  9185.             return "invalid digit";
  9186.         *out++ = (c1 << 4) + c;
  9187.     }
  9188.     switch(in[i]) {
  9189.     case 0:
  9190.     case '\r':
  9191.     case '\n':
  9192.         return NULL;
  9193.     default:
  9194.         return "extra characters at end of input";
  9195.     }
  9196. }
  9197. #endif /* COMMENT */
  9198.  
  9199. /* ck_krb4_initTGT() returns 0 on success */
  9200. int
  9201. #ifdef CK_ANSIC
  9202. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  9203. #else
  9204. ck_krb4_initTGT(op,init)
  9205.     struct krb_op_data * op, struct krb4_init_data * init
  9206. #endif
  9207. {
  9208.     char    aname[ANAME_SZ+1];
  9209.     char    inst[INST_SZ+1];
  9210.     char    realm[REALM_SZ+1];
  9211.     char    *password=NULL;
  9212.     char    passwd[80]="";
  9213.     char    *username = NULL;
  9214.     char    *usernameptr=NULL;
  9215.     int     iflag,      /* Instance */
  9216.             rflag,      /* Realm */
  9217.             vflag,      /* Verbose */
  9218.             lflag,      /* Lifetime */
  9219.             pflag,      /* Preauth */
  9220.             lifetime=KRB_DEFAULT_LIFE,   /* Life Time */
  9221.             k_errno;
  9222.     register char *cp;
  9223.     register i;
  9224.  
  9225.     if ( !ck_krb4_is_installed() )
  9226.         return(-1);
  9227.  
  9228.     *inst = *realm = '\0';
  9229.     iflag = rflag = vflag = lflag = pflag = 0;
  9230.  
  9231.     vflag = init->verbose;
  9232.     pflag = init->preauth;
  9233.  
  9234.     if ( init->lifetime ) {
  9235.         lifetime = init->lifetime<5?1:init->lifetime/5;
  9236.         if ( lifetime > 255 ) lifetime = 255;
  9237.     }
  9238.     else
  9239.         lifetime = KRB_DEFAULT_LIFE;
  9240.  
  9241.     username = init->principal;
  9242.  
  9243.     if (username && username[0] &&
  9244.         (k_errno = kname_parse(aname, inst, realm, username))
  9245.         != AUTH_SUCCESS) {
  9246.         krb4_errno = k_errno;
  9247.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9248.         printf("%s\r\n", krb_get_err_text_entry(k_errno));
  9249.         iflag = rflag = 1;
  9250.         username = NULL;
  9251.     }
  9252.  
  9253.     if ( init->realm ) {
  9254.         ckstrncpy(realm,init->realm,REALM_SZ);
  9255.     }
  9256.  
  9257.     if ( init->instance ) {
  9258.         ckstrncpy(inst,init->instance, INST_SZ);
  9259.     }
  9260.  
  9261. #ifdef COMMENT
  9262.     if ( vflag )
  9263.         printf("Kerberos IV initialization\r\n");
  9264. #endif /* COMMENT */
  9265.  
  9266.     if (!username || !username[0]) {
  9267.         debug(F100,"ck_krb4_initTGT no username specified","",0);
  9268.         printf("?Invalid principal specified.\r\n");
  9269.         krb4_errno = -1;
  9270.         makestr(&krb4_errmsg,"No principal specified");
  9271.         return(-1);
  9272.     }
  9273.     if (!*realm) {
  9274.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
  9275.     }
  9276.  
  9277.     if ( init->password )
  9278.         password = init->password;
  9279.     else {
  9280.         char prmpt[80];
  9281.         int ok;
  9282.  
  9283.         ckmakxmsg(prmpt,sizeof(prmpt),
  9284.                   "Kerberos 4 Password for ",username,"@",realm,": ",
  9285.                    NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9286.         ok = uq_txt(NULL,prmpt,2,NULL,passwd,80,NULL,DEFAULT_UQ_TIMEOUT);
  9287.         if ( ok )
  9288.             password = passwd;
  9289.     }
  9290.  
  9291.     if (pflag) {
  9292.         k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
  9293.                                              "krbtgt", realm,
  9294.                                              lifetime,
  9295.                                              password);
  9296.         if (k_errno == -1) {    /* preauth method not available */
  9297.             k_errno = krb_get_pw_in_tkt(aname,
  9298.                                          inst, realm,
  9299.                                          "krbtgt", realm,
  9300.                                          lifetime,
  9301.                                          password);
  9302.         }
  9303.     } else {
  9304.         k_errno = krb_get_pw_in_tkt(aname,
  9305.                                      inst, realm,
  9306.                                      "krbtgt", realm,
  9307.                                      lifetime,
  9308.                                      password);
  9309.     }
  9310.  
  9311.     memset(passwd,0,sizeof(passwd));
  9312.     if (k_errno) {
  9313.         printf("%s for principal %s%s%s@%s\r\n",
  9314.                 krb_get_err_text_entry(k_errno), aname,
  9315.                 inst[0]?".":"", inst, realm);
  9316.         krb4_errno = k_errno;
  9317.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9318.         return(-1);
  9319.     } else if (vflag) {
  9320.         printf("Result from realm %s: ", realm);
  9321.         printf("%s\r\n", krb_get_err_text_entry(k_errno));
  9322.     }
  9323.     krb4_errno = k_errno;
  9324.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9325.     return(0);
  9326. }
  9327. #endif /* KINIT */
  9328. #ifdef KDESTROY
  9329. int
  9330. #ifdef CK_ANSIC
  9331. ck_krb4_destroy(struct krb_op_data * op)
  9332. #else
  9333. ck_krb4_destroy(op) struct krb_op_data * op;
  9334. #endif
  9335. {
  9336.     int k_errno=0;
  9337.  
  9338.     if ( !ck_krb4_is_installed() )
  9339.         return(-1);
  9340.  
  9341.     k_errno = dest_tkt();
  9342.  
  9343.     krb4_errno = k_errno;
  9344.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9345.  
  9346.     if (k_errno == 0)
  9347.         printf("Tickets destroyed.\r\n");
  9348.     else if (k_errno == RET_TKFIL)
  9349.         printf("No tickets to destroy.\r\n");
  9350.     else {
  9351.         printf("Tickets MAY NOT be destroyed.\r\n");
  9352.         return(-1);
  9353.     }
  9354.     return(0);
  9355. }
  9356. #endif /* KDESTROY */
  9357. #ifdef KLIST
  9358. _PROTOTYP(static int display_tktfile,(char *, int, int, int));
  9359.  
  9360. int
  9361. #ifdef CK_ANSIC
  9362. ck_krb4_list_creds(struct krb_op_data * op)
  9363. #else
  9364. ck_krb4_list_creds(op) struct krb_op_data * op;
  9365. #endif
  9366. {
  9367.     int     long_form = 1;
  9368.     int     tgt_test = 0;
  9369.     int     do_srvtab = 0;
  9370.     int     show_kvnos = 0;
  9371.     char   *tkt_file = NULL;
  9372.  
  9373.     if ( !ck_krb4_is_installed() )
  9374.         return(-1);
  9375.  
  9376.     if ( op->cache )
  9377.         tkt_file = op->cache;
  9378.  
  9379.     if ( k4debug ) {
  9380.         show_kvnos = 1;
  9381.     }
  9382.  
  9383.     if (do_srvtab)
  9384.         return(display_srvtab(tkt_file));
  9385.     else
  9386.         return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
  9387. }
  9388.  
  9389. #ifndef KRB5
  9390. static int timestamp_width=0;
  9391.  
  9392. static char   *
  9393. #ifdef CK_ANSIC
  9394. short_date(long   *dp)
  9395. #else
  9396. short_date(dp) long   *dp;
  9397. #endif
  9398. {
  9399.     register char *cp;
  9400.     extern char *ctime();
  9401.     cp = ctime(dp) + 4;
  9402.     cp[15] = '\0';
  9403.     return (cp);
  9404. }
  9405.  
  9406.  
  9407. static VOID
  9408. #ifdef CK_ANSIC
  9409. printtime(time_t tv)
  9410. #else
  9411. printtime(tv) time_t tv;
  9412. #endif
  9413. {
  9414.     char timestring[BUFSIZ];
  9415.     char format[12];
  9416.     char fill;
  9417.  
  9418.     fill = ' ';
  9419.     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
  9420.     printf(format,short_date(&tv));
  9421. }
  9422. #endif /* KRB5 */
  9423.  
  9424. static int
  9425. #ifdef CK_ANSIC
  9426. display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
  9427. #else
  9428. display_tktfile(file,tgt_test,long_form,show_kvnos)
  9429.     char *file; int tgt_test; int long_form; int show_kvnos;
  9430. #endif
  9431. {
  9432.     char    pname[ANAME_SZ];
  9433.     char    pinst[INST_SZ];
  9434.     char    prealm[REALM_SZ];
  9435.     char    buf1[20], buf2[20];
  9436.     int     k_errno;
  9437. #ifdef OS2
  9438.     LEASH_CREDENTIALS creds;
  9439. #else /* OS2 */
  9440.     CREDENTIALS creds;
  9441. #endif /* OS2 */
  9442.     int     header = 1;
  9443.  
  9444.     file = tkt_string();
  9445.  
  9446.     if (long_form) {
  9447.         printf("Ticket cache:      %s\r\n", file);
  9448.     }
  9449.  
  9450.     /*
  9451.      * Since krb_get_tf_realm will return a ticket_file error,
  9452.      * we will call tf_init and tf_close first to filter out
  9453.      * things like no ticket file.  Otherwise, the error that
  9454.      * the user would see would be
  9455.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9456.      * instead of
  9457.      * klist: No ticket file (tf_util)
  9458.      */
  9459.  
  9460.     /* Open ticket file */
  9461.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9462.         if (!tgt_test)
  9463.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9464.         krb4_errno = k_errno;
  9465.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9466.         return(-1);
  9467.     }
  9468.  
  9469.  
  9470.     /* Close ticket file */
  9471.     (void) tf_close();
  9472.  
  9473.     /*
  9474.      * We must find the realm of the ticket file here before calling
  9475.      * tf_init because since the realm of the ticket file is not
  9476.      * really stored in the principal section of the file, the
  9477.      * routine we use must itself call tf_init and tf_close.
  9478.      */
  9479.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9480.         if (!tgt_test)
  9481.             printf("can't find realm of ticket file: %s\r\n",
  9482.                     krb_get_err_text_entry (k_errno));
  9483.         krb4_errno = k_errno;
  9484.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9485.         return(-1);
  9486.     }
  9487.  
  9488.     /* Open ticket file */
  9489.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9490.         if (!tgt_test)
  9491.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9492.         krb4_errno = k_errno;
  9493.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9494.         return(-1);
  9495.     }
  9496.     /* Get principal name and instance */
  9497.     if ((k_errno = tf_get_pname(pname)) ||
  9498.          (k_errno = tf_get_pinst(pinst))) {
  9499.         (void) tf_close();
  9500.         if (!tgt_test)
  9501.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9502.         krb4_errno = k_errno;
  9503.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9504.         return(-1);
  9505.     }
  9506.  
  9507.     /*
  9508.      * You may think that this is the obvious place to get the
  9509.      * realm of the ticket file, but it can't be done here as the
  9510.      * routine to do this must open the ticket file.  This is why
  9511.      * it was done before tf_init.
  9512.      */
  9513.  
  9514.     if (!tgt_test && long_form)
  9515.         printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
  9516.                (pinst[0] ? "." : ""), pinst,
  9517.                (prealm[0] ? "@" : ""), prealm);
  9518.  
  9519.     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
  9520.         if (!tgt_test && long_form && header) {
  9521.             printf("%-17s  %-17s  %s\r\n",
  9522.                    "Valid starting", "Expires", "Service principal");
  9523.             header = 0;
  9524.         }
  9525.         if (tgt_test) {
  9526.             creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  9527.             if (!strcmp(creds.service, "krbtgt") &&
  9528.                 !strcmp(creds.instance, prealm)) {
  9529.                 krb4_errno = k_errno;
  9530.                 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9531.  
  9532.                 (void) tf_close();
  9533.                 if (time(0) < creds.issue_date) {
  9534.                     return(0);          /* tgt hasn't expired */
  9535.                 } else {
  9536.                     return(-1);         /* has expired */
  9537.                 }
  9538.             }
  9539.             continue;                   /* not a tgt */
  9540.         }
  9541.         if (long_form) {
  9542.             timestamp_width = 17;       /* for k5 display function */
  9543.                                         /* if available            */
  9544.             printtime(creds.issue_date);
  9545.             printf("  ");
  9546.             creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  9547.             if ( time(0) < creds.issue_date )
  9548.                 printtime(creds.issue_date);
  9549.             else
  9550.                 printf("*** expired ***  ");
  9551.             printf("  ");
  9552.         }
  9553.         if (show_kvnos)
  9554.           printf("%s%s%s%s%s (%d)\r\n",
  9555.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9556.                  (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
  9557.         else
  9558.           printf("%s%s%s%s%s\r\n",
  9559.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9560.                  (creds.realm[0] ? "@" : ""), creds.realm);
  9561.  
  9562. #ifdef OS2
  9563.         if ( creds.address[0] )
  9564.             printf("   Address: %s\r\n",creds.address);
  9565. #endif /* OS2 */
  9566.     }
  9567.  
  9568.     (void) tf_close();
  9569.  
  9570.     if (tgt_test) {
  9571.         return(-1);
  9572.     }/* no tgt found */
  9573.     if (header && long_form && k_errno == EOF) {
  9574.         printf("No tickets in file.\r\n");
  9575.     }
  9576.     krb4_errno = k_errno;
  9577.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9578.     return(0);
  9579. }
  9580.  
  9581. #ifdef COMMENT
  9582. /* Just so we remember what the command line interface looked like */
  9583. usage()
  9584. {
  9585.     printf(
  9586.         "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
  9587.     return(-1);
  9588. }
  9589. #endif /* COMMENT */
  9590.  
  9591. /* adapted from getst() in librkb */
  9592. /*
  9593.  * ok_getst() takes a file descriptor, a string and a count.  It reads
  9594.  * from the file until either it has read "count" characters, or until
  9595.  * it reads a null byte.  When finished, what has been read exists in
  9596.  * the given string "s".  If "count" characters were actually read, the
  9597.  * last is changed to a null, so the returned string is always null-
  9598.  * terminated.  ok_getst() returns the number of characters read, including
  9599.  * the null terminator.
  9600.  *
  9601.  * If there is a read error, it returns -1 (like the read(2) system call)
  9602.  */
  9603.  
  9604. static int
  9605. #ifdef CK_ANSIC
  9606. ok_getst(int fd, register char *s, int n)
  9607. #else
  9608. ok_getst(fd, s, n) int fd; register char *s; int n;
  9609. #endif
  9610. {
  9611.     register int count = n;
  9612.     int err;
  9613.     while ((err = read(fd, s, 1)) > 0 && --count)
  9614.         if (*s++ == '\0')
  9615.             return (n - count);
  9616.     if (err < 0)
  9617.         return(-1);
  9618.     *s = '\0';
  9619.     return (n - count);
  9620. }
  9621.  
  9622. int
  9623. #ifdef CK_ANSIC
  9624. display_srvtab(char *file)
  9625. #else
  9626. display_srvtab(file) char *file;
  9627. #endif
  9628. {
  9629.     int stab;
  9630.     char serv[SNAME_SZ];
  9631.     char inst[INST_SZ];
  9632.     char rlm[REALM_SZ];
  9633.     unsigned char key[8];
  9634.     unsigned char vno;
  9635.     int count;
  9636.  
  9637.     printf("Server key file:   %s\r\n", file);
  9638. #ifdef NT
  9639. #ifndef O_RDONLY
  9640. #define O_RDONLY _O_RDONLY
  9641. #endif /* O_RDONLY */
  9642. #endif /* NT */
  9643.  
  9644.     if ((stab = open(file, O_RDONLY, 0400)) < 0) {
  9645.         perror(file);
  9646.         return(-1);
  9647.     }
  9648.     printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
  9649.            "Key Version");
  9650.     printf("------------------------------------------------------\r\n");
  9651.  
  9652.     /* argh. getst doesn't return error codes, it silently fails */
  9653.     while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
  9654.            && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
  9655.            && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
  9656.         if (((count = read(stab,(char *) &vno,1)) != 1) ||
  9657.              ((count = read(stab,(char *) key,8)) != 8)) {
  9658.             if (count < 0)
  9659.                 perror("reading from key file");
  9660.             else
  9661.                 printf("key file truncated\r\n");
  9662.             return(-1);
  9663.         }
  9664.         printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
  9665.     }
  9666.     if (count < 0)
  9667.         perror(file);
  9668.     (void) close(stab);
  9669.     return(0);
  9670. }
  9671. #endif /* KLIST */
  9672. #else /* KRB4 */
  9673. int
  9674. ck_krb4_autoget_TGT(char * dummy)
  9675. {
  9676.     return(-1);
  9677. }
  9678. #ifdef CK_KERBEROS
  9679. int
  9680. #ifdef CK_ANSIC
  9681. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  9682. #else
  9683. ck_krb4_initTGT(op,init)
  9684.     struct krb_op_data * op, struct krb4_init_data * init
  9685. #endif
  9686. {
  9687.     return(-1);
  9688. }
  9689.  
  9690. #ifdef CK_ANSIC
  9691. ck_krb4_destroy(struct krb_op_data * op)
  9692. #else
  9693. ck_krb4_destroy(op) struct krb_op_data * op;
  9694. #endif
  9695. {
  9696.     return(-1);
  9697. }
  9698. int
  9699. #ifdef CK_ANSIC
  9700. ck_krb4_list_creds(struct krb_op_data * op)
  9701. #else
  9702. ck_krb4_list_creds(op) struct krb_op_data * op;
  9703. #endif
  9704. {
  9705.     return(-1);
  9706. }
  9707. #else /* CK_KERBEROS */
  9708. int ck_krb4_initTGT(void * a, void *b)
  9709. {
  9710.     return(-1);
  9711. }
  9712. int ck_krb4_destroy(void *a)
  9713. {
  9714.     return(-1);
  9715. }
  9716. int ck_krb4_list_creds(void *a)
  9717. {
  9718.     return(-1);
  9719. }
  9720. #endif /* CK_KERBEROS */
  9721. #endif /* KRB4 */
  9722.  
  9723. /* The following functions are used to implement the Kermit Script Language */
  9724. /* functions                                                                */
  9725.  
  9726. struct tkt_list_item {
  9727.     char * name;
  9728.     struct tkt_list_item * next;
  9729. };
  9730.  
  9731. static struct tkt_list_item * k4_tkt_list = NULL;
  9732.  
  9733. int
  9734. #ifdef CK_ANSIC
  9735. ck_krb4_get_tkts(VOID)
  9736. #else
  9737. ck_krb4_get_tkts()
  9738. #endif
  9739. {
  9740. #ifdef KRB4
  9741.     char   *file=NULL;
  9742.     char    pname[ANAME_SZ];
  9743.     char    pinst[INST_SZ];
  9744.     char    prealm[REALM_SZ];
  9745.     char    buf1[20], buf2[20];
  9746.     int     k_errno;
  9747. #ifdef OS2
  9748.     LEASH_CREDENTIALS creds;
  9749. #else /* OS2 */
  9750.     CREDENTIALS creds;
  9751. #endif /* OS2 */
  9752.     int     tkt_count=0;
  9753.     struct  tkt_list_item ** list = &k4_tkt_list;
  9754.  
  9755.     while ( k4_tkt_list ) {
  9756.         struct tkt_list_item * next;
  9757.         next = k4_tkt_list->next;
  9758.         free(k4_tkt_list->name);
  9759.         free(k4_tkt_list);
  9760.         k4_tkt_list = next;
  9761.     }
  9762.  
  9763.     if ( !ck_krb4_is_installed() )
  9764.         return(-1);
  9765.  
  9766.     file = tkt_string();
  9767.  
  9768.     /*
  9769.      * Since krb_get_tf_realm will return a ticket_file error,
  9770.      * we will call tf_init and tf_close first to filter out
  9771.      * things like no ticket file.  Otherwise, the error that
  9772.      * the user would see would be
  9773.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9774.      * instead of
  9775.      * klist: No ticket file (tf_util)
  9776.      */
  9777.  
  9778.     /* Open ticket file */
  9779.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9780.         return(-1);
  9781.     }
  9782.  
  9783.     /* Close ticket file */
  9784.     (void) tf_close();
  9785.  
  9786.     /*
  9787.      * We must find the realm of the ticket file here before calling
  9788.      * tf_init because since the realm of the ticket file is not
  9789.      * really stored in the principal section of the file, the
  9790.      * routine we use must itself call tf_init and tf_close.
  9791.      */
  9792.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9793.         return(-1);
  9794.     }
  9795.  
  9796.     /* Open ticket file */
  9797.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9798.         return(-1);
  9799.     }
  9800.     /* Get principal name and instance */
  9801.     if ((k_errno = tf_get_pname(pname)) ||
  9802.          (k_errno = tf_get_pinst(pinst))) {
  9803.         return(-1);
  9804.     }
  9805.  
  9806.     /*
  9807.      * You may think that this is the obvious place to get the
  9808.      * realm of the ticket file, but it can't be done here as the
  9809.      * routine to do this must open the ticket file.  This is why
  9810.      * it was done before tf_init.
  9811.      */
  9812.  
  9813.     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
  9814.         char tkt_buf[256];
  9815.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9816.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9817.                  (creds.realm[0] ? "@" : ""), creds.realm,
  9818.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9819.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  9820.         (*list)->name = strdup(tkt_buf);
  9821.         (*list)->next = NULL;
  9822.         list = &((*list)->next);
  9823.         tkt_count++;
  9824.     }
  9825.  
  9826.     tf_close();
  9827.     return(tkt_count);
  9828. #else /* KRB4 */
  9829.     return(0);
  9830. #endif /* KRB4 */
  9831. }
  9832.  
  9833. char *
  9834. #ifdef CK_ANSIC
  9835. ck_krb4_get_next_tkt(VOID)
  9836. #else
  9837. ck_krb4_get_next_tkt()
  9838. #endif
  9839. {
  9840. #ifdef KRB4
  9841.     static char * s=NULL;
  9842.     struct tkt_list_item * next=NULL;
  9843.  
  9844.     if ( s ) {
  9845.         free(s);
  9846.         s = NULL;
  9847.     }
  9848.  
  9849.     if ( k4_tkt_list == NULL )
  9850.         return(NULL);
  9851.  
  9852.     next = k4_tkt_list->next;
  9853.     s = k4_tkt_list->name;
  9854.     free(k4_tkt_list);
  9855.     k4_tkt_list = next;
  9856.     return(s);
  9857. #else /* KRB4 */
  9858.     return(NULL);
  9859. #endif /* KRB4 */
  9860. }
  9861.  
  9862. int
  9863. #ifdef CK_ANSIC
  9864. ck_krb4_tkt_isvalid(char * tktname)
  9865. #else
  9866. ck_krb4_tkt_isvalid(tktname) char * tktname;
  9867. #endif
  9868. {
  9869. #ifdef KRB4
  9870.     char   *file=NULL;
  9871.     char    pname[ANAME_SZ];
  9872.     char    pinst[INST_SZ];
  9873.     char    prealm[REALM_SZ];
  9874.     char    buf1[20], buf2[20];
  9875.     int     k_errno;
  9876.     time_t  issue_t, expire_t, now_t;
  9877. #ifdef OS2
  9878.     LEASH_CREDENTIALS creds;
  9879. #else /* OS2 */
  9880.     CREDENTIALS creds;
  9881. #endif /* OS2 */
  9882.  
  9883.     if ( !ck_krb4_is_installed() )
  9884.         return(-1);
  9885.  
  9886.     debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
  9887.     file = tkt_string();
  9888.  
  9889.     /*
  9890.      * Since krb_get_tf_realm will return a ticket_file error,
  9891.      * we will call tf_init and tf_close first to filter out
  9892.      * things like no ticket file.  Otherwise, the error that
  9893.      * the user would see would be
  9894.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9895.      * instead of
  9896.      * klist: No ticket file (tf_util)
  9897.      */
  9898.  
  9899.     /* Open ticket file */
  9900.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  9901.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9902.         return(-1);
  9903.     }
  9904.  
  9905.     /* Close ticket file */
  9906.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9907.     (void) tf_close();
  9908.  
  9909.     /*
  9910.      * We must find the realm of the ticket file here before calling
  9911.      * tf_init because since the realm of the ticket file is not
  9912.      * really stored in the principal section of the file, the
  9913.      * routine we use must itself call tf_init and tf_close.
  9914.      */
  9915.     debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
  9916.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9917.         return(-1);
  9918.     }
  9919.  
  9920.     /* Open ticket file */
  9921.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  9922.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9923.         return(-1);
  9924.     }
  9925.     /* Get principal name and instance */
  9926.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
  9927.     if ((k_errno = tf_get_pname(pname)) ||
  9928.          (k_errno = tf_get_pinst(pinst))) {
  9929.  
  9930.         /* Close ticket file */
  9931.         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9932.         (void) tf_close();
  9933.  
  9934.         return(-1);
  9935.     }
  9936.  
  9937.     /*
  9938.      * You may think that this is the obvious place to get the
  9939.      * realm of the ticket file, but it can't be done here as the
  9940.      * routine to do this must open the ticket file.  This is why
  9941.      * it was done before tf_init.
  9942.      */
  9943.  
  9944.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
  9945.     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
  9946.         char tkt_buf[256];
  9947.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9948.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9949.                  (creds.realm[0] ? "@" : ""), creds.realm,
  9950.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9951.         if ( !strcmp(tktname,tkt_buf) ) {
  9952.  
  9953.             /* we found the ticket we are looking for */
  9954.             issue_t = creds.issue_date;
  9955.             expire_t = creds.issue_date
  9956.                 + ((unsigned char) creds.lifetime) * 5 * 60;
  9957.             now_t = time(0);
  9958.  
  9959.             /* We add a 5 minutes fudge factor to compensate for potential */
  9960.             /* clock skew errors between the KDC and K95's host OS         */
  9961.  
  9962.             if ( now_t >= (issue_t-300) && now_t < expire_t) {
  9963. #ifdef OS2
  9964. #ifdef CHECKADDRS
  9965.                 if ( krb4_checkaddrs ) {
  9966.                     extern char myipaddr[20];       /* From ckcnet.c */
  9967.                     if ( !myipaddr[0] ) {
  9968.                         int i;
  9969.                         char buf[60];
  9970.                         for ( i=0;i<64;i++ ) {
  9971.                             if ( getlocalipaddrs(buf,60,i) < 0 )
  9972.                                 break;
  9973.  
  9974.                             if ( !strcmp(buf,creds.address) ) {
  9975.                                 /* Close ticket file */
  9976.                                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9977.                                 (void) tf_close();
  9978.                                 return(1); /* They're the same */
  9979.                             }
  9980.                         }
  9981.  
  9982.                         /* Close ticket file */
  9983.                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9984.                         (void) tf_close();
  9985.                         return(0);                  /* They're different */
  9986.                     } else if ( strcmp(myipaddr,creds.address) ) {
  9987.                         /* Close ticket file */
  9988.                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9989.                         (void) tf_close();
  9990.                         return(0);                  /* They're different */
  9991.                     }
  9992.                     else {
  9993.                         /* Close ticket file */
  9994.                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9995.                         (void) tf_close();
  9996.                         return(1);                  /* They're the same */
  9997.                     }
  9998.                 } else {
  9999.                     /* Close ticket file */
  10000.                     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  10001.                     (void) tf_close();
  10002.                     return(1);                  /* They're the same */
  10003.                 }
  10004. #else /* CHECKADDRS */
  10005.                 /* Close ticket file */
  10006.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  10007.                 (void) tf_close();
  10008.                 return(1);      /* valid but no ip address check */
  10009. #endif /* CHECKADDRS */
  10010. #else /* OS2 */
  10011.                 /* Close ticket file */
  10012.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  10013.                 (void) tf_close();
  10014.                 return(1);      /* Valid but no ip address check */
  10015. #endif /* OS2 */
  10016.             }
  10017.             else {
  10018.                 /* Close ticket file */
  10019.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  10020.                 (void) tf_close();
  10021.                 return(0);      /* expired or otherwise invalid */
  10022.             }
  10023.         }
  10024.     }
  10025.     /* Close ticket file */
  10026.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  10027.     (void) tf_close();
  10028.     return(0);                  /* could not find the desired ticket */
  10029. #else /* KRB4 */
  10030.     return(-1);
  10031. #endif /* KRB4 */
  10032. }
  10033.  
  10034. int
  10035. #ifdef CK_ANSIC
  10036. ck_krb4_is_tgt_valid(VOID)
  10037. #else
  10038. ck_krb4_is_tgt_valid()
  10039. #endif
  10040. {
  10041. #ifdef KRB4
  10042.     char tgt[256];
  10043.     char * s;
  10044.     int rc = 0;
  10045.  
  10046.     s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
  10047.     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",s,"@",s);
  10048.     rc = ck_krb4_tkt_isvalid(tgt);
  10049.     debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
  10050.     return(rc > 0);
  10051. #else /* KRB4 */
  10052.     return(0);
  10053. #endif /* KRB4 */
  10054. }
  10055.  
  10056. int
  10057. #ifdef CK_ANSIC
  10058. ck_krb4_tkt_time(char * tktname)
  10059. #else
  10060. ck_krb4_tkt_time(tktname) char * tktname;
  10061. #endif
  10062. {
  10063. #ifdef KRB4
  10064.     char   *file=NULL;
  10065.     char    pname[ANAME_SZ];
  10066.     char    pinst[INST_SZ];
  10067.     char    prealm[REALM_SZ];
  10068.     char    buf1[20], buf2[20];
  10069.     int     k_errno;
  10070. #ifdef OS2
  10071.     LEASH_CREDENTIALS creds;
  10072. #else /* OS2 */
  10073.     CREDENTIALS creds;
  10074. #endif /* OS2 */
  10075.  
  10076.     if ( !ck_krb4_is_installed() )
  10077.         return(-1);
  10078.  
  10079.     file = tkt_string();
  10080.  
  10081.     /*
  10082.      * Since krb_get_tf_realm will return a ticket_file error,
  10083.      * we will call tf_init and tf_close first to filter out
  10084.      * things like no ticket file.  Otherwise, the error that
  10085.      * the user would see would be
  10086.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  10087.      * instead of
  10088.      * klist: No ticket file (tf_util)
  10089.      */
  10090.  
  10091.     /* Open ticket file */
  10092.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  10093.         return(-1);
  10094.     }
  10095.  
  10096.     /* Close ticket file */
  10097.     (void) tf_close();
  10098.  
  10099.     /*
  10100.      * We must find the realm of the ticket file here before calling
  10101.      * tf_init because since the realm of the ticket file is not
  10102.      * really stored in the principal section of the file, the
  10103.      * routine we use must itself call tf_init and tf_close.
  10104.      */
  10105.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  10106.         return(-1);
  10107.     }
  10108.  
  10109.     /* Open ticket file */
  10110.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  10111.         return(-1);
  10112.     }
  10113.     /* Get principal name and instance */
  10114.     if ((k_errno = tf_get_pname(pname)) ||
  10115.          (k_errno = tf_get_pinst(pinst))) {
  10116.         tf_close();
  10117.         return(-1);
  10118.     }
  10119.  
  10120.     /*
  10121.      * You may think that this is the obvious place to get the
  10122.      * realm of the ticket file, but it can't be done here as the
  10123.      * routine to do this must open the ticket file.  This is why
  10124.      * it was done before tf_init.
  10125.      */
  10126.  
  10127.     while ((k_errno = tf_get_cred(&creds)) == AUTH_SUCCESS) {
  10128.         char tkt_buf[256];
  10129.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  10130.                  creds.service, (creds.instance[0] ? "." : ""),
  10131.                  creds.instance,
  10132.                  (creds.realm[0] ? "@" : ""), creds.realm,
  10133.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  10134.         if ( !strcmp(tktname,tkt_buf) ) {
  10135.             /* we found the ticket we are looking for */
  10136.             int n = (creds.issue_date
  10137.                       + (((unsigned char) creds.lifetime) * 5 * 60))
  10138.                 - time(0);
  10139.             tf_close();
  10140.             return(n <= 0 ? 0 : n);
  10141.         }
  10142.     }
  10143.     tf_close();
  10144.     return(0);                  /* could not find the desired ticket */
  10145. #else /* KRB4 */
  10146.     return(-1);
  10147. #endif /* KRB4 */
  10148. }
  10149.  
  10150. char *
  10151. #ifdef CK_ANSIC
  10152. ck_krb4_getrealm(void)
  10153. #else
  10154. ck_krb4_getrealm()
  10155. #endif
  10156. {
  10157. #ifdef KRB4
  10158.     char   *file=NULL;
  10159.     int     k_errno;
  10160.     static char realm[256]="";
  10161.     realm[0]='\0';
  10162.  
  10163.     if ( !ck_krb4_is_installed() )
  10164.         return(realm);
  10165.  
  10166.     /* Try to get realm from ticket file */
  10167.     /* If failure get the local realm    */
  10168.  
  10169.     /*
  10170.     * Since krb_get_tf_realm will return a ticket_file error,
  10171.     * we will call tf_init and tf_close first to filter out
  10172.     * things like no ticket file.
  10173.     */
  10174.  
  10175.     /* Open ticket file */
  10176.     file = tkt_string();
  10177.     if (file == NULL || !file[0])
  10178.         return(realm);
  10179.  
  10180.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  10181.         /* Close ticket file */
  10182.         (void) tf_close();
  10183.  
  10184.         k_errno = krb_get_tf_realm(file, realm);
  10185.     }
  10186.     if (k_errno != KSUCCESS) {
  10187.         k_errno = krb_get_lrealm(realm, 1);
  10188.     }
  10189.     return(realm);
  10190. #else /* KRB4 */
  10191.     return("");
  10192. #endif /* KRB4 */
  10193. }
  10194.  
  10195. char *
  10196. #ifdef CK_ANSIC
  10197. ck_krb4_getprincipal(void)
  10198. #else
  10199. ck_krb4_getprincipal()
  10200. #endif
  10201. {
  10202. #ifdef KRB4
  10203.     char   *file=NULL;
  10204.     int     k_errno;
  10205.     static char principal[256]="";
  10206.     char        instance[256]="";
  10207.     char        realm[256]="";
  10208.     principal[0]='\0';
  10209.  
  10210.     if ( !ck_krb4_is_installed() )
  10211.         return(principal);
  10212.  
  10213.     /* Try to get realm from ticket file */
  10214.     /* If failure get the local realm    */
  10215.  
  10216.     /*
  10217.     * Since krb_get_tf_realm will return a ticket_file error,
  10218.     * we will call tf_init and tf_close first to filter out
  10219.     * things like no ticket file.
  10220.     */
  10221.  
  10222.     /* Open ticket file */
  10223.     file = tkt_string();
  10224.     if (file == NULL || !file[0])
  10225.         return(principal);
  10226.  
  10227.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  10228.         /* Close ticket file */
  10229.         (void) tf_close();
  10230.  
  10231.         k_errno = krb_get_tf_fullname(file, principal, instance, realm);
  10232.     }
  10233.     return(principal);
  10234. #else /* KRB4 */
  10235.     return("");
  10236. #endif /* KRB4 */
  10237. }
  10238.  
  10239. static struct tkt_list_item * k5_tkt_list = NULL;
  10240.  
  10241. int
  10242. #ifdef CK_ANSIC
  10243. ck_krb5_get_tkts(char * cc_name)
  10244. #else
  10245. ck_krb5_get_tkts(cc_name) char * cc_name;
  10246. #endif
  10247. {
  10248. #ifdef KRB5
  10249. #ifndef HEIMDAL
  10250.     krb5_context kcontext;
  10251.     krb5_error_code retval;
  10252.     krb5_ccache cache = NULL;
  10253.     krb5_cc_cursor cur;
  10254.     krb5_creds creds;
  10255.     krb5_principal princ=NULL;
  10256.     krb5_flags flags=0;
  10257.     krb5_error_code code=0;
  10258.     int exit_status = 0;
  10259.  
  10260.     int     tkt_count=0;
  10261.     struct  tkt_list_item ** list = &k5_tkt_list;
  10262.  
  10263.     while ( k5_tkt_list ) {
  10264.         struct tkt_list_item * next;
  10265.         next = k5_tkt_list->next;
  10266.         free(k5_tkt_list->name);
  10267.         free(k5_tkt_list);
  10268.         k5_tkt_list = next;
  10269.     }
  10270.  
  10271.     if ( !ck_krb5_is_installed() )
  10272.         return(-1);
  10273.  
  10274.     retval = krb5_init_context(&kcontext);
  10275.     if (retval) {
  10276.         debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
  10277.         return(-1);
  10278.     }
  10279.  
  10280.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10281.     if (code != 0) {
  10282.         debug(F111,"ck_krb5_get_tkts while getting ccache",
  10283.                error_message(code),code);
  10284.         tkt_count = -1;
  10285.         goto exit_k5_get_tkt;
  10286.     }
  10287.  
  10288.     flags = 0;                          /* turns off OPENCLOSE mode */
  10289.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10290.         if (code == ENOENT) {
  10291.             debug(F111,"ck_krb5_get_tkts (ticket cache)",
  10292.                    krb5_cc_get_name(kcontext, cache),code);
  10293.         } else {
  10294.             debug(F111,
  10295.                  "ck_krb5_get_tkts while setting cache flags (ticket cache)",
  10296.                   krb5_cc_get_name(kcontext, cache),code);
  10297.         }
  10298.         tkt_count = -1;
  10299.         goto exit_k5_get_tkt;
  10300.     }
  10301.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10302.         debug(F101,"ck_krb5_get_tkts while retrieving principal name",
  10303.                "",code);
  10304.         tkt_count = -1;
  10305.         goto exit_k5_get_tkt;
  10306.     }
  10307.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10308.         debug(F101,"ck_krb5_get_tkts while unparsing principal name",
  10309.                "",code);
  10310.         tkt_count = -1;
  10311.         goto exit_k5_get_tkt;
  10312.     }
  10313.  
  10314.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10315.         debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
  10316.                "",code);
  10317.         tkt_count = -1;
  10318.         goto exit_k5_get_tkt;
  10319.     }
  10320.  
  10321.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10322.         char *sname=NULL;
  10323.  
  10324.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10325.         if (retval) {
  10326.             debug(F101,
  10327.                   "ck_krb5_get_tkts while unparsing server name","",retval);
  10328.             tkt_count = -1;
  10329.             goto exit_k5_get_tkt;
  10330.         }
  10331.  
  10332.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  10333.         (*list)->name = sname;
  10334.         (*list)->next = NULL;
  10335.         list = &((*list)->next);
  10336.  
  10337.         krb5_free_unparsed_name(kcontext,sname);
  10338.         krb5_free_cred_contents(kcontext, &creds);
  10339.         tkt_count++;
  10340.     }
  10341.  
  10342.     if (code == KRB5_CC_END) {
  10343.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10344.             debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
  10345.                    "",code);
  10346.             tkt_count = -1;
  10347.             goto exit_k5_get_tkt;
  10348.         }
  10349.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10350.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10351.             debug(F101,"ck_krb5_get_tkts while closing ccache",
  10352.                    "",code);
  10353.             tkt_count = -1;
  10354.             goto exit_k5_get_tkt;
  10355.         }
  10356.     } else {
  10357.         debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
  10358.         tkt_count = -1;
  10359.         goto exit_k5_get_tkt;
  10360.     }
  10361.  
  10362.   exit_k5_get_tkt:
  10363.     krb5_free_principal(kcontext,princ);
  10364.     krb5_free_unparsed_name(kcontext,defname);
  10365.     krb5_cc_close(kcontext,cache);
  10366.     krb5_free_context(kcontext);
  10367.     return(tkt_count);
  10368. #else /* HEIMDAL */
  10369.     return(-1);
  10370. #endif /* HEIMDAL */
  10371. #else /* KRB5 */
  10372.     return(0);
  10373. #endif /* KRB5 */
  10374. }
  10375.  
  10376. char *
  10377. #ifdef CK_ANSIC
  10378. ck_krb5_get_next_tkt(VOID)
  10379. #else
  10380. ck_krb5_get_next_tkt()
  10381. #endif
  10382. {
  10383. #ifdef KRB5
  10384. #ifndef HEIMDAL
  10385.     static char * s=NULL;
  10386.     struct tkt_list_item * next=NULL;
  10387.  
  10388.     if ( s ) {
  10389.         free(s);
  10390.         s = NULL;
  10391.     }
  10392.  
  10393.     if ( k5_tkt_list == NULL )
  10394.         return(NULL);
  10395.  
  10396.     next = k5_tkt_list->next;
  10397.     s = k5_tkt_list->name;
  10398.     free(k5_tkt_list);
  10399.     k5_tkt_list = next;
  10400.     return(s);
  10401. #else /* HEIMDAL */
  10402.     return("Not implemented");
  10403. #endif /* HEIMDAL */
  10404. #else /* KRB5 */
  10405.     return(NULL);
  10406. #endif /* KRB5 */
  10407. }
  10408.  
  10409. char *
  10410. #ifdef CK_ANSIC
  10411. ck_krb5_tkt_flags(char * cc_name, char * tktname)
  10412. #else
  10413. ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
  10414. #endif
  10415. {
  10416. #ifdef KRB5
  10417. #ifndef HEIMDAL
  10418.     krb5_context kcontext;
  10419.     krb5_error_code retval;
  10420.     krb5_ccache cache = NULL;
  10421.     krb5_cc_cursor cur;
  10422.     krb5_creds creds;
  10423.     krb5_principal princ=NULL;
  10424.     krb5_flags flags=0;
  10425.     krb5_error_code code=0;
  10426.     char * flag_str = "";
  10427.  
  10428.     if ( !ck_krb5_is_installed() )
  10429.         return("");
  10430.  
  10431.     retval = krb5_init_context(&kcontext);
  10432.     if (retval) {
  10433.         debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
  10434.         return("");
  10435.     }
  10436.  
  10437.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10438.     if (code != 0) {
  10439.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  10440.                error_message(code),code);
  10441.         goto exit_k5_get_tkt;
  10442.     }
  10443.  
  10444.     flags = 0;                          /* turns off OPENCLOSE mode */
  10445.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10446.         if (code == ENOENT) {
  10447.             debug(F111,"ck_krb5_tkt_flags (ticket cache)",
  10448.                    krb5_cc_get_name(kcontext, cache),code);
  10449.         } else {
  10450.             debug(F111,
  10451.                  "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
  10452.                   krb5_cc_get_name(kcontext, cache),code);
  10453.         }
  10454.         retval = -1;
  10455.         goto exit_k5_get_tkt;
  10456.     }
  10457.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10458.         debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
  10459.                "",code);
  10460.         retval = -1;
  10461.         goto exit_k5_get_tkt;
  10462.     }
  10463.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10464.         debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
  10465.                "",code);
  10466.         retval = -1;
  10467.         goto exit_k5_get_tkt;
  10468.     }
  10469.  
  10470.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10471.         debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
  10472.                "",code);
  10473.         retval = -1;
  10474.         goto exit_k5_get_tkt;
  10475.     }
  10476.  
  10477.     if ((code = krb5_timeofday(kcontext, &now))) {
  10478.         if (!status_only)
  10479.             debug(F101,"ck_krb5_tkt_flags while getting time of day.",
  10480.                    "",code);
  10481.         retval = -1;
  10482.         goto exit_k5_get_tkt;
  10483.     }
  10484.  
  10485.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10486.         char *sname=NULL;
  10487.  
  10488.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10489.         if (retval) {
  10490.             debug(F101,
  10491.                   "ck_krb5_tkt_flags while unparsing server name","",retval);
  10492.             retval = -1;
  10493.             krb5_free_cred_contents(kcontext, &creds);
  10494.             goto exit_k5_get_tkt;
  10495.         }
  10496.  
  10497.         if ( !strcmp(sname,tktname) ) {
  10498.             /* we found the ticket we are looking for */
  10499.  
  10500.             flag_str = flags_string(&creds);
  10501.  
  10502.             krb5_free_unparsed_name(kcontext,sname);
  10503.             krb5_free_cred_contents(kcontext, &creds);
  10504.             code = KRB5_CC_END;
  10505.             break;
  10506.         }
  10507.         krb5_free_unparsed_name(kcontext,sname);
  10508.         krb5_free_cred_contents(kcontext, &creds);
  10509.     }
  10510.  
  10511.     if (code == KRB5_CC_END) {
  10512.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10513.             debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
  10514.                    "",code);
  10515.             goto exit_k5_get_tkt;
  10516.         }
  10517.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10518.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10519.             debug(F101,"ck_krb5_tkt_flags while closing ccache",
  10520.                    "",code);
  10521.             goto exit_k5_get_tkt;
  10522.         }
  10523.     } else {
  10524.         debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
  10525.         goto exit_k5_get_tkt;
  10526.     }
  10527.  
  10528.   exit_k5_get_tkt:
  10529.     krb5_free_principal(kcontext,princ);
  10530.     krb5_free_unparsed_name(kcontext,defname);
  10531.     krb5_cc_close(kcontext,cache);
  10532.     krb5_free_context(kcontext);
  10533.     return(flag_str);
  10534. #else /* HEIMDAL */
  10535.     return("Not implemented");
  10536. #endif /* HEIMDAL */
  10537. #else /* KRB5 */
  10538.     return("");
  10539. #endif /* KRB5 */
  10540. }
  10541.  
  10542.  
  10543. int
  10544. #ifdef CK_ANSIC
  10545. ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
  10546. #else
  10547. ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
  10548. #endif
  10549. {
  10550. #ifdef KRB5
  10551. #ifndef HEIMDAL
  10552.     krb5_context kcontext=NULL;
  10553.     krb5_error_code retval;
  10554.     krb5_ccache cache = NULL;
  10555.     krb5_cc_cursor cur;
  10556.     krb5_creds creds;
  10557.     krb5_principal princ=NULL;
  10558.     krb5_flags flags=0;
  10559.     krb5_error_code code=0;
  10560. #ifdef CHECKADDRS
  10561.     krb5_address **     myAddrs=NULL;
  10562.     krb5_address **     p=NULL;
  10563.     BOOL                Addrfound = FALSE;
  10564. #endif /*CHECKADDRS*/
  10565.  
  10566.     if ( !ck_krb5_is_installed() )
  10567.         return(-1);
  10568.  
  10569.     retval = krb5_init_context(&kcontext);
  10570.     if (retval) {
  10571.         debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
  10572.         return(-1);
  10573.     }
  10574.  
  10575.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10576.     if (code != 0) {
  10577.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  10578.                error_message(code),code);
  10579.         goto exit_k5_get_tkt;
  10580.     }
  10581.  
  10582.     flags = 0;                          /* turns off OPENCLOSE mode */
  10583.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10584.         if (code == ENOENT) {
  10585.             debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
  10586.                    krb5_cc_get_name(kcontext, cache),code);
  10587.         } else {
  10588.             debug(F111,
  10589.                 "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
  10590.                   krb5_cc_get_name(kcontext, cache),code);
  10591.         }
  10592.         retval = -1;
  10593.         goto exit_k5_get_tkt;
  10594.     }
  10595.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10596.         debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
  10597.                "",code);
  10598.         retval = -1;
  10599.         goto exit_k5_get_tkt;
  10600.     }
  10601.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10602.         debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
  10603.                "",code);
  10604.         retval = -1;
  10605.         goto exit_k5_get_tkt;
  10606.     }
  10607.  
  10608.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10609.         debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
  10610.                "",code);
  10611.         retval = -1;
  10612.         goto exit_k5_get_tkt;
  10613.     }
  10614.  
  10615.     if ((code = krb5_timeofday(kcontext, &now))) {
  10616.         if (!status_only)
  10617.             debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
  10618.                    "",code);
  10619.         retval = -1;
  10620.         goto exit_k5_get_tkt;
  10621.     }
  10622.  
  10623.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10624.         char *sname=NULL;
  10625.  
  10626.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10627.         if (retval) {
  10628.             debug(F101,
  10629.                   "ck_krb5_tkt_isvalid while unparsing server name","",retval);
  10630.             retval = -1;
  10631.             krb5_free_cred_contents(kcontext, &creds);
  10632.             goto exit_k5_get_tkt;
  10633.         }
  10634.  
  10635.         if ( !strcmp(sname,tktname) ) {
  10636.             /* we found the ticket we are looking for */
  10637.  
  10638.             /* We add a 5 minutes fudge factor to compensate for potential */
  10639.             /* clock skew errors between the KDC and K95's host OS         */
  10640.  
  10641.             retval = ((creds.times.starttime > 0) &&
  10642.                        now >= (creds.times.starttime - 300) &&
  10643.                        now < (creds.times.endtime + 300) &&
  10644.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  10645.  
  10646. #ifdef CHECKADDRS
  10647.             if ( retval && krb5_checkaddrs &&
  10648.                                  creds.addresses && creds.addresses[0] ) {
  10649.                 /* if we think it is valid, then lets check the IP Addresses */
  10650.                 /* to make sure it is valid for our current connection.      */
  10651.                 /* Also make sure it's for the correct IP address */
  10652.                 retval = krb5_os_localaddr(kcontext, &myAddrs);
  10653.                 if (retval) {
  10654.                     com_err(NULL, retval, "retrieving my IP address");
  10655.                     krb5_free_unparsed_name(kcontext,sname);
  10656.                     krb5_free_cred_contents(kcontext, &creds);
  10657.                     code = KRB5_CC_END;
  10658.                     retval = -1;
  10659.                     break;
  10660.                 }
  10661.  
  10662.              /* See if any of our addresses match any in cached credentials */
  10663.  
  10664.                 for (Addrfound=FALSE, p=myAddrs;
  10665.                      (Addrfound==FALSE) && (*p);
  10666.                      p++
  10667.                      ) {
  10668.                     if (krb5_address_search(kcontext, *p, creds.addresses)) {
  10669.                         Addrfound = TRUE;
  10670.                     }
  10671.                 }
  10672.                 krb5_free_addresses(k5_context, myAddrs);
  10673.  
  10674.                 if (Addrfound) {
  10675.                     krb5_free_unparsed_name(kcontext,sname);
  10676.                     krb5_free_cred_contents(kcontext, &creds);
  10677.                     code = KRB5_CC_END;
  10678.                     retval = 1;
  10679.                     break;
  10680.                 } else {
  10681.                     krb5_free_unparsed_name(kcontext,sname);
  10682.                     krb5_free_cred_contents(kcontext, &creds);
  10683.                     code = KRB5_CC_END;
  10684.                     retval = 0;
  10685.                     break;
  10686.                 }
  10687.             }
  10688. #endif /* CHECKADDRS */
  10689.  
  10690.             krb5_free_unparsed_name(kcontext,sname);
  10691.             krb5_free_cred_contents(kcontext, &creds);
  10692.             code = KRB5_CC_END;
  10693.             break;
  10694.         }
  10695.         krb5_free_unparsed_name(kcontext,sname);
  10696.         krb5_free_cred_contents(kcontext, &creds);
  10697.     }
  10698.  
  10699.     if (code == KRB5_CC_END) {
  10700.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10701.             debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
  10702.                    "",code);
  10703.             retval = -1;
  10704.             goto exit_k5_get_tkt;
  10705.         }
  10706.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10707.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10708.             debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
  10709.                    "",code);
  10710.             retval = -1;
  10711.             goto exit_k5_get_tkt;
  10712.         }
  10713.     } else {
  10714.         debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
  10715.         retval = -1;
  10716.         goto exit_k5_get_tkt;
  10717.     }
  10718.  
  10719.   exit_k5_get_tkt:
  10720.     krb5_free_principal(kcontext,princ);
  10721.     krb5_free_unparsed_name(kcontext,defname);
  10722.     krb5_cc_close(kcontext,cache);
  10723.     krb5_free_context(kcontext);
  10724.     return(retval);
  10725. #else /* HEIMDAL */
  10726.     return(-1);
  10727. #endif /* HEIMDAL */
  10728. #else /* KRB5 */
  10729.     return(-1);
  10730. #endif /* KRB5 */
  10731. }
  10732.  
  10733. int
  10734. #ifdef CK_ANSIC
  10735. ck_krb5_is_tgt_valid(VOID)
  10736. #else
  10737. ck_krb5_is_tgt_valid()
  10738. #endif
  10739. {
  10740. #ifdef KRB5
  10741. #ifndef HEIMDAL
  10742.     char tgt[256];
  10743.     char * s;
  10744.     int rc = 0;
  10745.  
  10746.     s = ck_krb5_getrealm(krb5_d_cc);
  10747.     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",s,"@",s);
  10748.     rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
  10749.     debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
  10750.     return(rc>0);
  10751. #else /* HEIMDAL */
  10752.     return(-1);
  10753. #endif /* HEIMDAL */
  10754. #else /* KRB5 */
  10755.     return(0);
  10756. #endif /* KRB5 */
  10757. }
  10758.  
  10759. int
  10760. #ifdef CK_ANSIC
  10761. ck_krb5_tkt_time(char * cc_name, char * tktname)
  10762. #else
  10763. ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
  10764. #endif
  10765. {
  10766. #ifdef KRB5
  10767. #ifndef HEIMDAL
  10768.     krb5_context kcontext;
  10769.     krb5_error_code retval;
  10770.     krb5_ccache cache = NULL;
  10771.     krb5_cc_cursor cur;
  10772.     krb5_creds creds;
  10773.     krb5_principal princ=NULL;
  10774.     krb5_flags flags=0;
  10775.     krb5_error_code code=0;
  10776.  
  10777.     if ( !ck_krb5_is_installed() )
  10778.         return(-1);
  10779.  
  10780.     retval = krb5_init_context(&kcontext);
  10781.     if (retval) {
  10782.         debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
  10783.         return(-1);
  10784.     }
  10785.  
  10786.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10787.     if (code != 0) {
  10788.         debug(F111,"ck_krb5_tkt_time while getting ccache",
  10789.                error_message(code),code);
  10790.         retval = -1;
  10791.         goto exit_k5_get_tkt;
  10792.     }
  10793.  
  10794.     flags = 0;                          /* turns off OPENCLOSE mode */
  10795.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10796.         if (code == ENOENT) {
  10797.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  10798.                    krb5_cc_get_name(kcontext, cache),code);
  10799.         } else {
  10800.             debug(F111,
  10801.                  "ck_krb5_list_creds while setting cache flags (ticket cache)",
  10802.                   krb5_cc_get_name(kcontext, cache),code);
  10803.         }
  10804.         retval = -1;
  10805.         goto exit_k5_get_tkt;
  10806.     }
  10807.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10808.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  10809.                "",code);
  10810.         retval = -1;
  10811.         goto exit_k5_get_tkt;
  10812.     }
  10813.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10814.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  10815.                "",code);
  10816.         retval = -1;
  10817.         goto exit_k5_get_tkt;
  10818.     }
  10819.  
  10820.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10821.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  10822.                "",code);
  10823.         retval = -1;
  10824.         goto exit_k5_get_tkt;
  10825.     }
  10826.  
  10827.     if ((code = krb5_timeofday(kcontext, &now))) {
  10828.         if (!status_only)
  10829.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  10830.                    "",code);
  10831.         krb5_free_context(kcontext);
  10832.         return(-1);
  10833.     }
  10834.  
  10835.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10836.         char *sname=NULL;
  10837.  
  10838.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10839.         if (retval) {
  10840.             debug(F101,
  10841.                   "ck_krb5_list_creds while unparsing server name","",retval);
  10842.             retval = -1;
  10843.             krb5_free_unparsed_name(kcontext,sname);
  10844.             krb5_free_cred_contents(kcontext, &creds);
  10845.             goto exit_k5_get_tkt;
  10846.         }
  10847.  
  10848.         if ( !strcmp(sname,tktname) ) {
  10849.             /* we found the ticket we are looking for */
  10850.             int valid = (creds.times.starttime &&
  10851.                        now > creds.times.starttime &&
  10852.                        now < creds.times.endtime &&
  10853.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  10854.             if ( valid ) {
  10855.                 retval = creds.times.endtime - now;
  10856.             }
  10857.             else
  10858.                 retval = 0;
  10859.             krb5_free_unparsed_name(kcontext,sname);
  10860.             krb5_free_cred_contents(kcontext, &creds);
  10861.             code = KRB5_CC_END;
  10862.             break;
  10863.         }
  10864.         krb5_free_unparsed_name(kcontext,sname);
  10865.         krb5_free_cred_contents(kcontext, &creds);
  10866.     }
  10867.  
  10868.     if (code == KRB5_CC_END) {
  10869.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10870.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  10871.                    "",code);
  10872.             retval = -1;
  10873.             goto exit_k5_get_tkt;
  10874.         }
  10875.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10876.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10877.             debug(F101,"ck_krb5_list_creds while closing ccache",
  10878.                    "",code);
  10879.             retval = -1;
  10880.             goto exit_k5_get_tkt;
  10881.         }
  10882.     } else {
  10883.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  10884.         retval = -1;
  10885.         goto exit_k5_get_tkt;
  10886.     }
  10887.  
  10888.   exit_k5_get_tkt:
  10889.     krb5_free_principal(kcontext,princ);
  10890.     krb5_free_unparsed_name(kcontext,defname);
  10891.     krb5_cc_close(kcontext,cache);
  10892.     krb5_free_context(kcontext);
  10893.     return(retval);
  10894. #else /* HEIMDAL */
  10895.     return(-1);
  10896. #endif /* HEIMDAL */
  10897. #else /* KRB5 */
  10898.     return(-1);
  10899. #endif /* KRB5 */
  10900. }
  10901.  
  10902. char *
  10903. #ifdef CK_ANSIC
  10904. ck_krb5_get_cc_name(void)
  10905. #else
  10906. ck_krb5_get_cc_name()
  10907. #endif
  10908. {
  10909. #ifdef KRB5
  10910. #ifndef HEIMDAL
  10911.     static char cc_name[CKMAXPATH+1]="";
  10912.     krb5_context kcontext = NULL;
  10913.     krb5_ccache ccache = NULL;
  10914.     krb5_error_code code;
  10915.     char * p=NULL;
  10916.  
  10917.     cc_name[0] = '\0';
  10918.  
  10919.     if ( !ck_krb5_is_installed() )
  10920.         return(cc_name);
  10921.  
  10922.     p = getenv("KRB5CCNAME");
  10923.     if ( !p ) {
  10924.         code = krb5_init_context(&kcontext);
  10925.         if (code) {
  10926.             com_err("ck_krb5_get_cc_name",code,"while init_context");
  10927.             return(cc_name);
  10928.         }
  10929.         if ((code = krb5_cc_default(kcontext, &ccache))) {
  10930.             com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
  10931.             goto exit_k5_get_cc;
  10932.         }
  10933.  
  10934.         ckmakmsg(cc_name,sizeof(cc_name),
  10935.                  (char *)krb5_cc_get_type(kcontext,ccache),":",
  10936.                  (char *)krb5_cc_get_name(kcontext,ccache),NULL);
  10937.     } else {
  10938.         ckstrncpy(cc_name,p,CKMAXPATH);
  10939.     }
  10940.  
  10941.     if ( !strncmp("FILE:",cc_name,5) ) {
  10942.         for ( p=cc_name; *p ; p++ )
  10943.             if ( *p == '\\' ) *p = '/';
  10944.     }
  10945.  
  10946.   exit_k5_get_cc:
  10947.     if ( ccache )
  10948.         krb5_cc_close(kcontext,ccache);
  10949.     if ( kcontext )
  10950.         krb5_free_context(kcontext);
  10951.     return(cc_name);
  10952. #else /* HEIMDAL */
  10953.     return("Not implemented");
  10954. #endif /* HEIMDAL */
  10955. #else /* KRB5 */
  10956.     return("");
  10957. #endif /* KRB5 */
  10958. }
  10959.  
  10960. char *
  10961. #ifdef CK_ANSIC
  10962. ck_krb5_getrealm(char * cc_name)
  10963. #else
  10964. ck_krb5_getrealm(cc_name) char * cc_name;
  10965. #endif
  10966. {
  10967. #ifdef KRB5
  10968. #ifndef HEIMDAL
  10969.     static char realm[256]="";
  10970.     krb5_context kcontext;
  10971.     krb5_ccache ccache = NULL;
  10972.     krb5_error_code code;
  10973.     krb5_principal me=NULL;
  10974.  
  10975.     realm[0] = '\0';
  10976.  
  10977.     if ( !ck_krb5_is_installed() )
  10978.         return(realm);
  10979.  
  10980.     code = krb5_init_context(&kcontext);
  10981.     if (code) {
  10982.         return(realm);
  10983.     }
  10984.  
  10985.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  10986.     if (code != 0) {
  10987.         goto exit_k5_getrealm;
  10988.     }
  10989.  
  10990.     code = krb5_cc_get_principal(kcontext, ccache, &me);
  10991.     if (code)
  10992.         code = krb5_parse_name(kcontext, "foo", &me);
  10993.     if (code) {
  10994.         goto exit_k5_getrealm;
  10995.     }
  10996.     if ( krb5_princ_realm(kcontext, me)->length < sizeof(realm) ) {
  10997.         memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  10998.                 krb5_princ_realm(kcontext, me)->length);        /* safe */
  10999.        realm[krb5_princ_realm(kcontext, me)->length]='\0';
  11000.     }
  11001.   exit_k5_getrealm:
  11002.     if ( me )
  11003.         krb5_free_principal(kcontext,me);
  11004.     if ( ccache )
  11005.         krb5_cc_close(kcontext,ccache);
  11006.     if (kcontext)
  11007.         krb5_free_context(kcontext);
  11008.     return(realm);
  11009. #else /* HEIMDAL */
  11010.     return("Not implemented");
  11011. #endif /* HEIMDAL */
  11012. #else /* KRB5 */
  11013.     return("");
  11014. #endif /* KRB5 */
  11015. }
  11016.  
  11017. char *
  11018. #ifdef CK_ANSIC
  11019. ck_krb5_getprincipal(char * cc_name)
  11020. #else
  11021. ck_krb5_getprincipal(cc_name) char * cc_name;
  11022. #endif
  11023. {
  11024. #ifdef KRB5
  11025. #ifndef HEIMDAL
  11026.     static char principal[UIDBUFLEN+1]="";
  11027.     krb5_context kcontext;
  11028.     krb5_ccache ccache = NULL;
  11029.     krb5_error_code code;
  11030.     krb5_principal me;
  11031.     char * p=NULL;
  11032.     int i;
  11033.  
  11034.     principal[0] = '\0';
  11035.  
  11036.     if ( !ck_krb5_is_installed() )
  11037.         return(principal);
  11038.  
  11039.     code = krb5_init_context(&kcontext);
  11040.     if (code) {
  11041.         return(principal);
  11042.     }
  11043.  
  11044.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  11045.     if (code != 0) {
  11046.         goto exit_k5_getprincipal;
  11047.     }
  11048.  
  11049.     if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
  11050.         goto exit_k5_getprincipal;
  11051.     }
  11052.  
  11053.     if ((code = krb5_unparse_name (kcontext, me, &p))) {
  11054.         krb5_free_principal(kcontext,me);
  11055.         goto exit_k5_getprincipal;
  11056.     }
  11057.  
  11058.     ckstrncpy(principal,p,UIDBUFLEN);
  11059.     i = ckindex("@",principal,0,0,0);
  11060.     if (i)
  11061.       principal[i-1] = '\0';
  11062.  
  11063.     krb5_free_unparsed_name(kcontext,p);
  11064.  
  11065.   exit_k5_getprincipal:
  11066.     if ( ccache )
  11067.         krb5_cc_close(kcontext,ccache);
  11068.     if (kcontext)
  11069.         krb5_free_context(kcontext);
  11070.     return(principal);
  11071. #else /* HEIMDAL */
  11072.     return("Not implemented");
  11073. #endif /* HEIMDAL */
  11074. #else /* KRB5 */
  11075.     return("");
  11076. #endif /* KRB5 */
  11077. }
  11078.  
  11079. #ifndef CRYPT_DLL
  11080. int
  11081. ck_get_crypt_table(struct keytab ** pTable, int * pN)
  11082. {
  11083. #ifdef CK_ENCRYPTION
  11084.     return(get_crypt_table(pTable, pN));
  11085. #else /* ENCRYPTION */
  11086.     int i=0;
  11087. #ifndef OS2
  11088.     char * tmpstring = NULL;
  11089. #endif /* OS2 */
  11090.  
  11091.     if ( *pTable )
  11092.     {
  11093.         for ( i=0 ; i < *pN ; i++ )
  11094.             free( (*pTable)[i].kwd ) ;
  11095.         free ( *pTable )  ;
  11096.     }
  11097.     *pTable = NULL;
  11098.     *pN = 0;
  11099.  
  11100.     *pTable = malloc( sizeof(struct keytab) * 2 ) ;
  11101.     if ( !(*pTable) )
  11102.         return(0);
  11103.  
  11104. #ifdef OS2
  11105.     (*pTable)[0].kwd =strdup("automatic");
  11106. #else /* OS2 */
  11107.     makestr(&tmpstring,"automatic");
  11108.     (*pTable)[0].kwd = tmpstring;
  11109.     tmpstring = NULL;
  11110. #endif /* OS2 */
  11111.     (*pTable)[0].kwval = ENCTYPE_ANY;
  11112.     (*pTable)[0].flgs = 0;
  11113. #ifdef OS2
  11114.     (*pTable)[1].kwd =strdup("none");
  11115. #else /* OS2 */
  11116.     makestr(&tmpstring,"none");
  11117.     (*pTable)[1].kwd = tmpstring;
  11118.     tmpstring = NULL;
  11119. #endif /* OS2 */
  11120.     (*pTable)[1].kwval = 999;
  11121.     (*pTable)[1].flgs = 0;
  11122.     (*pN) = 2;
  11123.  
  11124.     return(2);
  11125. #endif /* ENCRYPTION */
  11126. }
  11127.  
  11128. VOID
  11129. ck_encrypt_send_support()
  11130. {
  11131. #ifdef CK_ENCRYPTION
  11132.     encrypt_send_support();
  11133. #endif /* ENCRYPTION */
  11134. }
  11135. #endif /* CRYPT_DLL */
  11136.  
  11137. /*
  11138.  *
  11139.  * Kstream
  11140.  *
  11141.  * Emulates the kstream package in Kerberos 4
  11142.  *
  11143.  */
  11144.  
  11145. int
  11146. kstream_destroy()
  11147. {
  11148.     if (g_kstream != NULL) {
  11149.         auth_destroy();                       /* Destroy authorizing */
  11150.         free(g_kstream);
  11151.         g_kstream=NULL;
  11152.     }
  11153.     return 0;
  11154. }
  11155.  
  11156. VOID
  11157. #ifdef CK_ANSIC
  11158. kstream_set_buffer_mode(int mode)
  11159. #else
  11160. kstream_set_buffer_mode(mode) int mode;
  11161. #endif
  11162. {
  11163. }
  11164.  
  11165.  
  11166. int
  11167. #ifdef CK_ANSIC
  11168. kstream_create_from_fd(int fd,
  11169.                        kstream_ptr data)
  11170. #else
  11171. kstream_create_from_fd(fd,data)
  11172.     int fd; kstream_ptr data;
  11173. #endif
  11174. {
  11175.     int n;
  11176.  
  11177.     g_kstream = malloc(sizeof(struct kstream_int));
  11178.     if (g_kstream == NULL)
  11179.         return 0;
  11180.  
  11181.     g_kstream->fd = fd;
  11182.  
  11183.     n = auth_init(g_kstream);                   /* Initialize authorizing */
  11184.     if (n) {
  11185.         free(g_kstream);
  11186.         g_kstream = NULL;
  11187.         return 0;
  11188.     }
  11189.  
  11190.     g_kstream->encrypt = NULL;
  11191.     g_kstream->decrypt = NULL;
  11192.     g_kstream->encrypt_type = ENCTYPE_ANY;
  11193.     g_kstream->decrypt_type = ENCTYPE_ANY;
  11194.     return 1;
  11195. }
  11196.  
  11197. #ifdef CK_KERBEROS
  11198. #ifdef RLOGCODE
  11199. static int do_lencheck, use_ivecs;
  11200. extern int rlog_inband;
  11201.  
  11202. #ifdef KRB5
  11203. void
  11204. rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client,
  11205.                            protonum)
  11206.      krb5_keyblock *in_keyblock;
  11207.      int encrypt_flag;
  11208.      int lencheck;
  11209.      int am_client;
  11210.      enum krb5_kcmd_proto protonum;
  11211. {
  11212.     krb5_error_code status;
  11213.     size_t blocksize;
  11214.  
  11215.     if (!encrypt_flag)
  11216.         return;
  11217.  
  11218.     desinbuf.data = des_inbuf;
  11219.     desoutbuf.data = des_outpkt+4;      /* Set up des buffers */
  11220.     k5_session_key = in_keyblock;
  11221.  
  11222.     do_lencheck = lencheck;
  11223.  
  11224.     if ( protonum == KCMD_OLD_PROTOCOL ) {
  11225.         use_ivecs = 0;
  11226.         return;
  11227.     }
  11228.  
  11229.     use_ivecs = 1;
  11230.  
  11231.     if (status = krb5_c_block_size(k5_context, k5_session_key->enctype,
  11232.                                    &blocksize)) {
  11233.         /* XXX what do I do? */
  11234.         printf("fatal kerberos 5 crypto library error\n");
  11235.         ttclos(0);
  11236.         return;
  11237.     }
  11238.  
  11239.     encivec_i[0].length = encivec_i[1].length = 
  11240.     encivec_o[0].length = encivec_o[1].length = blocksize;
  11241.  
  11242.     if ((encivec_i[0].data = malloc(encivec_i[0].length * 4)) == NULL) {
  11243.         /* XXX what do I do? */
  11244.         printf("fatal malloc failed\n");
  11245.         ttclos(0);
  11246.         return;
  11247.     }
  11248.  
  11249.     encivec_i[1].data = encivec_i[0].data + encivec_i[0].length;
  11250.     encivec_o[0].data = encivec_i[1].data + encivec_i[1].length;
  11251.     encivec_o[1].data = encivec_o[0].data + encivec_o[0].length;
  11252.  
  11253.     /* is there a better way to initialize this? */
  11254.     memset(encivec_i[0].data, am_client, blocksize);
  11255.     memset(encivec_o[0].data, 1 - am_client, blocksize);
  11256.     memset(encivec_i[1].data, 2 | am_client, blocksize);
  11257.     memset(encivec_o[1].data, 2 | (1 - am_client), blocksize);
  11258. }
  11259. #endif /* KRB5 */
  11260.  
  11261. int
  11262. #ifdef CK_ANSIC
  11263. ck_krb_rlogin(CHAR * hostname, int port,
  11264.                CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
  11265.                struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
  11266.                int kversion, int encrypt_flag)
  11267. #else /* CK_ANSIC */
  11268. ck_krb_rlogin(hostname, port,
  11269.                localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
  11270.     CHAR * hostname; int port;
  11271.     CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
  11272.     struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
  11273.     int kversion; int encrypt_flag;
  11274. #endif /* CK_ANSIC */
  11275. {
  11276.     unsigned long status;
  11277.     char * realm=NULL;
  11278.     extern int ttyfd;
  11279.     int c;
  11280.     long msglen;
  11281.  
  11282.     debug(F111,"ck_krb_rlogin",hostname,port);
  11283.  
  11284.     if ( kversion == 4 && !ck_krb4_is_installed() ) {
  11285.         printf("?Kerberos 4 is not installed\r\n");
  11286.         return(-1);
  11287.     } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
  11288.         printf("?Kerberos 5 is not installed\r\n");
  11289.         return(-1);
  11290.     }
  11291.  
  11292.     if ( encrypt_flag && !ck_crypt_is_installed() ) {
  11293.         printf("?Encryption is not installed\r\n");
  11294.         return(-1);
  11295.     }
  11296.  
  11297.     if ( kversion == 5 ) {
  11298. #ifdef KRB5
  11299.         krb5_flags authopts=0;
  11300.         krb5_ccache ccache=NULL;
  11301.         char *cksumbuf=NULL;
  11302.         char *service=NULL;
  11303.         char * kcmd_version=NULL;
  11304.         enum krb5_kcmd_proto use_proto;
  11305.         krb5_data cksumdat;
  11306.         krb5_creds *get_cred = 0;
  11307.         krb5_error_code status;
  11308.         krb5_error      *error = 0;
  11309.         krb5_ap_rep_enc_part *rep_ret = NULL;
  11310.         krb5_data outbuf;
  11311.         int rc;
  11312.         krb5_int32 seqno=0;
  11313.         krb5_int32 server_seqno=0;
  11314.         char ** realmlist=NULL;
  11315.         int buflen;
  11316.         char tgt[256];
  11317.  
  11318.         debug(F100,"ck_krb_rlogin version 5","",0);
  11319.  
  11320.         realm = ck_krb5_realmofhost((char *)hostname);
  11321.         if (!realm) {
  11322.             ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
  11323.             ckstrncat(strTmp, (char *)hostname,AUTHTMPBL);
  11324.             ckstrncat(strTmp, "\"",AUTHTMPBL);
  11325.             printf("?Kerberos 5 error: %s\r\n",strTmp);
  11326.             krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
  11327.             makestr(&krb5_errmsg,strTmp);
  11328.             return(0);
  11329.         }
  11330.  
  11331.         ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  11332.         debug(F110,"ck_rlog_rlogin TGT",tgt,0);
  11333.         if ( krb5_autoget &&
  11334.              !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  11335.                 (ck_krb5_is_tgt_valid() > 0)) )
  11336.             ck_krb5_autoget_TGT(realm);
  11337.  
  11338.         buflen = strlen((char *)term_speed) + strlen((char *)remoteuser) + 64;
  11339.         if ((cksumbuf = malloc(buflen)) == 0) {
  11340.             printf("Unable to allocate memory for checksum buffer.\r\n");
  11341.             return(-1);
  11342.         }
  11343.         ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),":",
  11344.          (char *)term_speed,(char *)remoteuser);
  11345.         cksumdat.data = cksumbuf;
  11346.         cksumdat.length = strlen(cksumbuf);
  11347.  
  11348.         status = krb5_init_context(&k5_context);
  11349.         if (status) {
  11350.             debug(F110,"ck_krb_rlogin()","unable to init_context",0);
  11351.             return(-1);
  11352.         }
  11353.  
  11354.         desinbuf.data = des_inbuf;
  11355.         desoutbuf.data = des_outpkt+4;  /* Set up des buffers */
  11356.  
  11357.         rc = k5_get_ccache(k5_context,&ccache,NULL);
  11358.         if (rc != 0) {
  11359.             com_err(NULL, rc, "while getting ccache.");
  11360.             return(0);
  11361.         }
  11362.  
  11363.         service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
  11364.  
  11365.         if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
  11366.             printf("ck_krb_rlogin: no memory\r\n");
  11367.             return(-1);
  11368.         }
  11369.         memset(get_cred,0,sizeof(krb5_creds));
  11370.         status = krb5_sname_to_principal(k5_context, (char *) hostname,
  11371.                      service, KRB5_NT_SRV_HST,
  11372.                      &get_cred->server);
  11373.         if (status) {
  11374.             printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
  11375.                      error_message(status));
  11376.             return(-1);
  11377.         }
  11378.  
  11379.         ttoc(0);
  11380.  
  11381.         if (status = krb5_cc_get_principal(k5_context,
  11382.                                            ccache,
  11383.                                            &get_cred->client)
  11384.             ) {
  11385.             (void) krb5_cc_close(k5_context, ccache);
  11386.             krb5_free_creds(k5_context, get_cred);
  11387.             goto bad;
  11388.         }
  11389.  
  11390.         if (krb5_rlog_ver == KCMD_OLD_PROTOCOL)
  11391.             get_cred->keyblock.enctype=ENCTYPE_DES_CBC_CRC;
  11392.  
  11393.         /* Get ticket from credentials cache or kdc */
  11394.         status = krb5_get_credentials(k5_context,
  11395.                                       0,
  11396.                                       ccache,
  11397.                                       get_cred,
  11398.                                       &ret_cred
  11399.                                       );
  11400.         krb5_free_creds(k5_context, get_cred);
  11401.         get_cred = NULL;
  11402.         (void) krb5_cc_close(k5_context, ccache);
  11403.  
  11404.         if (status) 
  11405.             goto bad;
  11406.  
  11407.         /* Reset internal flags; these should not be set. */
  11408.         authopts &= (~OPTS_FORWARD_CREDS);
  11409.         authopts &= (~OPTS_FORWARDABLE_CREDS);
  11410.  
  11411.         if (krb5_auth_con_init(k5_context, &auth_context))
  11412.             goto bad;
  11413.  
  11414.         if (krb5_auth_con_setflags(k5_context, auth_context,
  11415.                                     KRB5_AUTH_CONTEXT_RET_TIME))
  11416.             goto bad;
  11417.  
  11418.         /* Only need local address for mk_cred() to send to krlogind */
  11419.         if (!krb5_d_no_addresses)
  11420.             if (status = krb5_auth_con_genaddrs(k5_context,
  11421.                                                 auth_context,
  11422.                                                  ttyfd,
  11423.                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
  11424.                                                  ))
  11425.                 goto bad;
  11426.  
  11427.         /* Here is where we start to handle the new protocol in earnest */
  11428.         if ( krb5_rlog_ver == KCMD_PROTOCOL_COMPAT_HACK ) {
  11429.             krb5_boolean is_des;
  11430.  
  11431.             if (status = krb5_c_enctype_compare( k5_context,
  11432.                                                  ENCTYPE_DES_CBC_CRC,
  11433. #ifdef HEIMDAL
  11434.                                                  ret_cred->session.keytype,
  11435. #else /* HEIMDAL */
  11436.                                                  ret_cred->keyblock.enctype,
  11437. #endif /* HEIMDAL */
  11438.                                                  &is_des)) {
  11439.                 krb5_free_creds(k5_context, ret_cred);
  11440.                 ret_cred = NULL;
  11441.                 goto bad;
  11442.             }
  11443.  
  11444.             if ( is_des ) {
  11445.                 kcmd_version = "KCMDV0.1";
  11446.                 use_proto = KCMD_OLD_PROTOCOL;
  11447.             } else {
  11448.                 authopts = AP_OPTS_USE_SUBKEY;
  11449.                 kcmd_version = "KCMDV0.2";
  11450.                 use_proto = KCMD_NEW_PROTOCOL;
  11451.             }
  11452.         } else {
  11453.             use_proto = krb5_rlog_ver;
  11454.             switch ( krb5_rlog_ver ) {
  11455.             case KCMD_NEW_PROTOCOL:
  11456.                 authopts = AP_OPTS_USE_SUBKEY;
  11457.                 kcmd_version = "KCMDV0.2";
  11458.                 break;
  11459.             case KCMD_OLD_PROTOCOL:
  11460.                 kcmd_version = "KCMDV0.1";
  11461.                 break;
  11462.             default:
  11463.                 goto bad;
  11464.             }
  11465.         }
  11466.  
  11467.         /* call Kerberos library routine to obtain an authenticator,
  11468.            pass it over the socket to the server, and obtain mutual
  11469.            authentication.
  11470.          */
  11471.         status = krb5_sendauth(k5_context,
  11472.                                &auth_context,
  11473.                                (krb5_pointer) &ttyfd,
  11474.                                kcmd_version,
  11475.                                ret_cred->client,
  11476.                                ret_cred->server,
  11477.                                 authopts,
  11478.                                &cksumdat,
  11479.                                ret_cred,
  11480.                                0,
  11481.                                &error,
  11482.                                &rep_ret,
  11483.                                NULL
  11484.                                );
  11485.         krb5_free_data_contents(k5_context,&cksumdat);
  11486.  
  11487.         if (status) {
  11488.             if ( !quiet )
  11489.                 printf("Couldn't authenticate to server: %s\r\n",
  11490.                         error_message(status));
  11491.             if (error) {
  11492.                 if ( !quiet ) {
  11493.                     printf("Server returned error code %d (%s)\r\n",
  11494.                         error->error,
  11495.                         error_message(ERROR_TABLE_BASE_krb5 + error->error));
  11496.                     if (error->text.length) {
  11497.                         printf("Error text sent from server: %s\r\n",
  11498.                                 error->text.data);
  11499.                     }
  11500.                 }
  11501.                 krb5_free_error(k5_context, error);
  11502.                 error = 0;
  11503.             }
  11504.             goto bad;
  11505.         }
  11506.  
  11507.         if (rep_ret) {
  11508.             server_seqno = rep_ret->seq_number;
  11509.             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
  11510.         }
  11511.  
  11512.         (void) ttol(remoteuser, strlen((char *)remoteuser)+1);
  11513.         (void) ttol(term_speed, strlen((char *)term_speed)+1);
  11514.         (void) ttol(localuser, strlen((char *)localuser)+1);
  11515.  
  11516.         if (forward_flag) {   /* Forward credentials (global) */
  11517.             if (status = krb5_fwd_tgt_creds( k5_context,
  11518.                                              auth_context,
  11519.                                              (char *)hostname,
  11520.                                              ret_cred->client,
  11521.                                              ret_cred->server,
  11522.                                              0,
  11523.                                              (forwardable_flag ?
  11524.                                                OPTS_FORWARDABLE_CREDS :
  11525.                                                0),
  11526.                                              &outbuf
  11527.                                              )
  11528.                  )
  11529.             {
  11530.                 printf("Error forwarding credentials: %s\r\n",
  11531.                          error_message(status));
  11532.                 goto bad2;
  11533.             }
  11534.  
  11535.             /* Send forwarded credentials */
  11536.             status = krb5_write_message(k5_context,
  11537.                                          (krb5_pointer)&ttyfd,
  11538.                                          &outbuf
  11539.                                          );
  11540.         }
  11541.         else { /* Dummy write to signal no forwarding */
  11542.           bad2:
  11543.             outbuf.length = 0;
  11544.             status = krb5_write_message(k5_context,
  11545.                                          (krb5_pointer)&ttyfd,
  11546.                                          &outbuf);
  11547.         }       
  11548.  
  11549.         if ((c = ttinc(0)) < 0) {
  11550.             if (c==-1) {
  11551.                 perror((char *)hostname);
  11552.             } else {
  11553.                 printf("ck_krb_rlogin: bad connection with remote host\r\n");
  11554.             }
  11555.             status = -1;
  11556.             goto bad;
  11557.         }
  11558.         if (c != 0) {
  11559.             while ((c = ttinc(1)) >= 0) {
  11560.                 (void) printf("%c",c);
  11561.                 if (c == '\n')
  11562.                     break;
  11563.             }
  11564.             status = -1;
  11565.             goto bad;
  11566.         }
  11567.  
  11568.         if ( status == 0 ) {        /* success */
  11569.             krb5_keyblock * key = 0;
  11570.  
  11571.             if ( use_proto == KCMD_NEW_PROTOCOL ) {
  11572.                 int on = 1;
  11573.                 rlog_inband = 1;
  11574.                 setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,
  11575.                            (char *) &on, sizeof on);
  11576.  
  11577.                 status = krb5_auth_con_getlocalsubkey( k5_context,
  11578.                                                        auth_context,
  11579.                                                        &key);
  11580.                 if ((status || !key) && encrypt_flag )
  11581.                     goto bad2;
  11582.             }
  11583.             if ( key == 0 ) {
  11584. #ifdef HEIMDAL
  11585.                 key = &ret_cred->session;
  11586. #else /* HEIMDAL */
  11587.                 key = &ret_cred->keyblock;
  11588. #endif /* HEIMDAL */
  11589.             }
  11590.  
  11591.             rcmd_stream_init_krb5(key, encrypt_flag, 1, 1, use_proto);
  11592.             if ( encrypt_flag )
  11593.                 rlog_encrypt = 1;
  11594.         }
  11595.         return (0);     /* success */
  11596.  
  11597.       bad:
  11598.         if ( status && !quiet ) {
  11599.             printf("Kerberos authentication error: %s\r\n",
  11600.                     error_message(status));
  11601.         }
  11602.         if (ret_cred) {
  11603.             krb5_free_creds(k5_context, ret_cred);
  11604.             ret_cred = NULL;
  11605.         }
  11606.         return (status);
  11607. #else /* KRB5 */
  11608.         return(-1);
  11609. #endif /* KRB5 */
  11610.     } else if (kversion == 4) {
  11611. #ifdef KRB4
  11612.         char tgt[4*REALM_SZ+1];
  11613.         debug(F100,"ck_krb_rlogin version 4","",0);
  11614.  
  11615.         realm = (char *)krb_realmofhost(hostname);
  11616.         if (!realm) {
  11617.             strcpy(strTmp, "Can't find realm for host \"");
  11618.             ckstrncat(strTmp, hostname,AUTHTMPBL);
  11619.             ckstrncat(strTmp, "\"",AUTHTMPBL);
  11620.             printf("?Kerberos 4 error: %s\r\n",strTmp);
  11621.             krb4_errno = 0;
  11622.             makestr(&krb4_errmsg,strTmp);
  11623.             return(0);
  11624.         }
  11625.  
  11626.         ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
  11627.         status = ck_krb4_tkt_isvalid(tgt);
  11628.  
  11629.         if ( status <= 0 && krb4_autoget )
  11630.             ck_krb4_autoget_TGT(realm);
  11631.  
  11632.         ttoc(0);        /* write a NUL */
  11633.  
  11634.         status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
  11635.                                ttyfd,
  11636.                                &k4_auth,
  11637.                                krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  11638.                                hostname,
  11639.                                realm,
  11640.                                (unsigned long) getpid(),
  11641.                                &k4_msg_data,
  11642.                                &cred,
  11643. #ifdef CK_ENCRYPTION
  11644.                                &k4_sched,
  11645. #else /* ENCRYPTION */
  11646.                                NULL,
  11647. #endif /* ENCRYPTION */
  11648.                                l_addr,
  11649.                                r_addr,
  11650.                                "KCMDV0.1");
  11651.         debug(F111,"ck_krb_rlogin","krb_sendauth",status);
  11652.         if (status != KSUCCESS) {
  11653.             printf( "krb_sendauth failed: %s\r\n",
  11654.                     krb_get_err_text_entry(status)
  11655.                     );
  11656.             return(-1);
  11657.         }
  11658.         ttol(remoteuser,strlen(remoteuser)+1);
  11659.         ttol(term_speed,strlen(term_speed)+1);
  11660.  
  11661.       reread:
  11662.         if ((c = ttinc(0)) < 0) {
  11663.             printf("rcmd: bad connection with remote host\r\n");
  11664.             return(-1);
  11665.         }
  11666.         debug(F111,"ck_krb_rlogin","first byte",c);
  11667.  
  11668.         if (c != 0) {
  11669.             char *check = "ld.so: warning:";
  11670.             /* If rlogind was compiled on SunOS4, and it somehow
  11671.             got the shared library version numbers wrong, it
  11672.             may give an ld.so warning about an old version of a
  11673.             shared library.  Just ignore any such warning.
  11674.             Note that the warning is a characteristic of the
  11675.             server; we may not ourselves be running under
  11676.             SunOS4.  */
  11677.             if (c == 'l') {
  11678.                 char *p;
  11679.                 char cc;
  11680.  
  11681.                 p = &check[1];
  11682.                 while ((c = ttinc(0)) >= 0) {
  11683.                     if (*p == '\0') {
  11684.                         if (c == '\n')
  11685.                             break;
  11686.                     } else {
  11687.                         if (c != *p)
  11688.                             break;
  11689.                         ++p;
  11690.                     }
  11691.                 }
  11692.  
  11693.                 if (*p == '\0')
  11694.                     goto reread;
  11695.             }
  11696.  
  11697.             printf(check);
  11698.             while ((c = ttinc(1)) >= 0) {
  11699.                 printf("%c",c);
  11700.                 if (c == '\n')
  11701.                     break;
  11702.             }
  11703.             debug(F110,"ck_krb_rlogin","fatal error 1",0);
  11704.             return(-1);
  11705.         }
  11706.  
  11707. #ifdef CK_ENCRYPTION
  11708.         if ( encrypt_flag ) {
  11709.             /* if we are encrypting we need to setup the encryption */
  11710.             /* routines.                                            */
  11711.             des_key_sched(cred.session, k4_sched);
  11712.             rlog_encrypt = 1;
  11713.         }
  11714. #endif /* ENCRYPTION */
  11715. #else /* KRB4 */
  11716.         return(-1);
  11717. #endif /* KRB4 */
  11718.     }
  11719.     return(0); /* success */
  11720. }
  11721.  
  11722. #define SRAND   srand
  11723. #define RAND    rand
  11724. #define RAND_TYPE       int
  11725.  
  11726. static long
  11727. random_confounder(size, fillin)
  11728. size_t size;
  11729. char * fillin;
  11730. {
  11731.     static int seeded = 0;
  11732.     register unsigned char *real_fill;
  11733.     RAND_TYPE   rval;
  11734.  
  11735.     if (!seeded) {
  11736.         /* time() defined in 4.12.2.4, but returns a time_t, which is an
  11737.            "arithmetic type" (4.12.1) */
  11738.         rval = (RAND_TYPE) time(0);
  11739.         SRAND(rval);
  11740.         rval = RAND();
  11741.         rval ^= getpid();
  11742.         SRAND(rval);
  11743.         seeded = 1;
  11744.     }
  11745.  
  11746.     real_fill = (unsigned char *)fillin;
  11747.     while (size > 0) {
  11748.         rval = RAND();
  11749.         *real_fill = rval & 0xff;
  11750.         real_fill++;
  11751.         size--;
  11752.         if (size) {
  11753.             *real_fill = (rval >> 8) & 0xff;
  11754.             real_fill++;
  11755.             size--;
  11756.         }
  11757.     }
  11758.     return 0;
  11759. }
  11760.  
  11761. #ifdef KRB5
  11762. int
  11763. krb5_des_avail(fd)
  11764.     int fd;
  11765. {
  11766.     return(nstored);
  11767. }
  11768.  
  11769. int
  11770. krb5_des_read(fd, buf, len, secondary)
  11771.     int fd;
  11772.     register char *buf;
  11773.     int len;
  11774.     int secondary;
  11775. {
  11776.     int nreturned = 0;
  11777.     long net_len,rd_len;
  11778.     int cc;
  11779.     krb5_error_code status;
  11780.     unsigned char c;
  11781.     krb5_data plain;
  11782.     krb5_enc_data cipher;
  11783.  
  11784.     debug(F111,"krb5_des_read","len",len);
  11785.     debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
  11786.     if ( !rlog_encrypt ) {
  11787.         cc = net_read(fd, buf, len);
  11788.         debug(F111,"krb5_des_read","chars read",cc);
  11789.         if ( cc < 0 )
  11790.             netclos();
  11791.         return(cc);
  11792.     }
  11793.  
  11794.     if (nstored >= len) {
  11795.         if ( buf ) {
  11796.             memcpy(buf, store_ptr, len);        /* safe */
  11797.             store_ptr += len;
  11798.             nstored -= len;
  11799.             return(len);
  11800.         } else
  11801.             return(0);
  11802.     } else if (nstored) {
  11803.         if ( buf ) {
  11804.             memcpy(buf, store_ptr, nstored);    /* safe */
  11805.             nreturned += nstored;
  11806.             buf += nstored;
  11807.             len -= nstored;
  11808.             nstored = 0;
  11809.         }
  11810.         else
  11811.             return(0);
  11812.     }
  11813.  
  11814.     /* See the comment in v4_des_read. */
  11815.     while (1) {
  11816.         cc = net_read(fd, &c, 1);
  11817.         /* we should check for non-blocking here, but we'd have
  11818.         to make it save partial reads as well. */
  11819.         if (cc <= 0) {
  11820.             return cc; /* read error */
  11821.         }
  11822.         if (cc == 1) {
  11823.             if (c == 0 || !do_lencheck) 
  11824.                 break;
  11825.         }
  11826.     }
  11827.  
  11828.     rd_len = c;
  11829.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11830.     rd_len = (rd_len << 8) | c;
  11831.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11832.     rd_len = (rd_len << 8) | c;
  11833.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11834.     rd_len = (rd_len << 8) | c;
  11835.  
  11836.     if (status = krb5_c_encrypt_length(k5_context, 
  11837.                                     k5_session_key->enctype,
  11838.                                     use_ivecs ? rd_len + 4 : rd_len,
  11839.                     (size_t *)&net_len)) {
  11840.         errno = status;
  11841.         return(-1);
  11842.     }
  11843.  
  11844.     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
  11845.         /* preposterous length; assume out-of-sync; only
  11846.            recourse is to close connection, so return 0 */
  11847.         printf("Read size problem.\r\n");
  11848.         return(0);
  11849.     }
  11850.     if ((cc = net_read(fd, desinbuf.data, net_len)) != net_len )
  11851.     {
  11852.         /* pipe must have closed, return 0 */
  11853.         printf( "Read error: length received %d != expected %d.\r\n",
  11854.                 cc,
  11855.                 net_len
  11856.                 );
  11857.         return(cc);
  11858.     }
  11859.  
  11860.  
  11861.     /* decrypt info */
  11862.     cipher.enctype = ENCTYPE_UNKNOWN;
  11863.     cipher.ciphertext.length = net_len;
  11864.     cipher.ciphertext.data = desinbuf.data;
  11865.     plain.length = sizeof(storage);
  11866.     plain.data = storage;
  11867.  
  11868.     if ( status = krb5_c_decrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
  11869.                                  use_ivecs ? encivec_i + secondary : 0,
  11870.                                   &cipher,&plain) ) {
  11871.         /* probably out of sync */
  11872.         printf("Cannot decrypt data from network: %s\r\n",
  11873.                  error_message(status));
  11874.         errno = EIO;
  11875.         return(-1);
  11876.     }
  11877.     
  11878.     store_ptr = storage;
  11879.     nstored = rd_len;
  11880.  
  11881.     if ( use_ivecs ) {
  11882.         int rd_len2;
  11883.         rd_len2 = storage[0] & 0xff;
  11884.         rd_len2 <<= 8; rd_len2 |= storage[1] & 0xff;
  11885.         rd_len2 <<= 8; rd_len2 |= storage[2] & 0xff;
  11886.         rd_len2 <<= 8; rd_len2 |= storage[3] & 0xff;
  11887.         if (rd_len2 != rd_len) {
  11888.             /* cleartext length trashed? */
  11889.             errno = EIO;
  11890.             return -1;
  11891.         }
  11892.         store_ptr += 4;
  11893.     }
  11894.  
  11895.     if ( !buf )
  11896.         return(0);
  11897.  
  11898. #ifdef RLOGCODE                         /* blah */
  11899.     if (rlog_inband && (ttnproto == NP_K5LOGIN || ttnproto == NP_EK5LOGIN))
  11900.     {
  11901.         int i, left, n;
  11902.  
  11903.         for (i = 0; i < nstored; i++) {
  11904.             if (store_ptr[i] == '\377' &&
  11905.                 store_ptr[i+1] == '\377') {
  11906.                 left = nstored - i;
  11907.                 n = rlog_ctrl(&store_ptr[i], left);
  11908.                 if (n < 0) {
  11909.                     left -= (-n);
  11910.                     nstored = left;
  11911.                     /* flush before, and (-n) bytes */
  11912.                     if (left > 0)
  11913.                         memmove(store_ptr, &store_ptr[i-n], left);
  11914.                 } else if (n) {
  11915.                     left -= n;
  11916.                     nstored -= n;
  11917.                     if (left > 0)
  11918.                         memmove(store_ptr, &store_ptr[n], left);
  11919.                 }
  11920.             }
  11921.         }
  11922.     }
  11923. #endif /* RLOGCODE */
  11924.  
  11925.     if (nstored > len) {
  11926.         memcpy(buf, store_ptr, len);            /* safe */
  11927.         nreturned += len;
  11928.         store_ptr += len;
  11929.         nstored -= len;
  11930.     } else {
  11931.         memcpy(buf, store_ptr, nstored);        /* safe */
  11932.         nreturned += nstored;
  11933.         nstored = 0;
  11934.     }
  11935.     return(nreturned);
  11936. }
  11937.  
  11938. int
  11939. krb5_des_write(fd, buf, len, secondary)
  11940.     int fd;
  11941.     char *buf;
  11942.     int len;
  11943.     int secondary;
  11944. {
  11945.     char tmpbuf[2*RLOG_BUFSIZ+8];
  11946.     unsigned char *len_buf = (unsigned char *) tmpbuf;
  11947.     krb5_error_code status;
  11948.     krb5_data plain;
  11949.     krb5_enc_data cipher;
  11950.  
  11951.     debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
  11952.     if ( !rlog_encrypt ) {
  11953.         int cc = net_write(fd, buf, len);
  11954.         debug(F111,"net_write","chars written",cc);
  11955.         return(cc != len ? -1 : len);
  11956.     }
  11957.  
  11958.     if (use_ivecs) {
  11959.         unsigned char *lenbuf2 = (unsigned char *) tmpbuf;
  11960.         if (len + 4 > sizeof(tmpbuf))
  11961.             abort ();
  11962.         lenbuf2[0] = (len & 0xff000000) >> 24;
  11963.         lenbuf2[1] = (len & 0xff0000) >> 16;
  11964.         lenbuf2[2] = (len & 0xff00) >> 8;
  11965.         lenbuf2[3] = (len & 0xff);
  11966.         memcpy (tmpbuf + 4, buf, len);
  11967.  
  11968.         plain.data = tmpbuf;
  11969.         plain.length = len + 4;
  11970.     } else {
  11971.         plain.data = buf;
  11972.         plain.length = len;
  11973.     }
  11974.  
  11975.     cipher.ciphertext.length = sizeof(des_outpkt)-4;
  11976.     cipher.ciphertext.data = desoutbuf.data;
  11977.  
  11978.     if ( status = krb5_c_encrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
  11979.                          use_ivecs ? encivec_o + secondary : 0,
  11980.                          &plain, &cipher)) {
  11981.         printf("Write encrypt problem: %s.\r\n",
  11982.                  error_message(status));
  11983.         errno = EIO;
  11984.         return(-1);
  11985.     }
  11986.     desoutbuf.length = cipher.ciphertext.length;
  11987.  
  11988.     len_buf = (unsigned char *) des_outpkt;
  11989.     len_buf[0] = (len & 0xff000000) >> 24;
  11990.     len_buf[1] = (len & 0xff0000) >> 16;
  11991.     len_buf[2] = (len & 0xff00) >> 8;
  11992.     len_buf[3] = (len & 0xff);
  11993.  
  11994.     if (net_write(fd, des_outpkt,desoutbuf.length+4)
  11995.          != desoutbuf.length+4){
  11996.         printf("Could not write out all data\r\n");
  11997.         return(-1);
  11998.     }
  11999.     else return(len);
  12000. }
  12001. #endif /* KRB5 */
  12002.  
  12003. #ifdef KRB4
  12004. /*
  12005.  * Note that the encrypted rlogin packets take the form of a four-byte
  12006.  * length followed by encrypted data.  On writing the data out, a significant
  12007.  * performance penalty is suffered (at least one RTT per character, two if we
  12008.  * are waiting for a shell to echo) by writing the data separately from the
  12009.  * length.  So, unlike the input buffer, which just contains the output
  12010.  * data, the output buffer represents the entire packet.
  12011.  */
  12012.  
  12013. int
  12014. krb4_des_avail(fd)
  12015.     int fd;
  12016. {
  12017.     return(nstored);
  12018. }
  12019.  
  12020. int
  12021. krb4_des_read(fd, buf, len)
  12022. int fd;
  12023. register char *buf;
  12024. int len;
  12025. {
  12026.     int nreturned = 0;
  12027.     unsigned long net_len, rd_len;
  12028.     int cc;
  12029.     unsigned char c;
  12030.     int gotzero = 0;
  12031.  
  12032.     debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
  12033.     debug(F111,"krb4_des_read","len",len);
  12034.     if ( !rlog_encrypt ) {
  12035.         cc = net_read(fd, buf, len);
  12036.         debug(F111,"krb4_des_read","chars read",cc);
  12037.         if ( cc < 0 )
  12038.             netclos();
  12039.         return(cc);
  12040.     }
  12041.  
  12042.     if (nstored >= len) {
  12043.         if ( buf ) {
  12044.             debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
  12045.             memcpy(buf, store_ptr, len);        /* safe */
  12046.             store_ptr += len;
  12047.             nstored -= len;
  12048.             return(len);
  12049.         } else
  12050.             return(0);
  12051.     } else if (nstored) {
  12052.         if ( buf ) {
  12053.             debug(F111,"krb4_des_read (nstored)","nstored",nstored);
  12054.             memcpy(buf, store_ptr, nstored);    /* safe */
  12055.             nreturned += nstored;
  12056.             buf += nstored;
  12057.             len -= nstored;
  12058.             nstored = 0;
  12059.         } else
  12060.             return(0);
  12061.     }
  12062.  
  12063.     /* We're fetching the length which is MSB first, and the MSB
  12064.     has to be zero unless the client is sending more than 2^24
  12065.     (16M) bytes in a single write (which is why this code is in
  12066.     rlogin but not rcp or rsh.) The only reasons we'd get something
  12067.     other than zero are:
  12068.     -- corruption of the tcp stream (which will show up when
  12069.     everything else is out of sync too)
  12070.     -- un-caught Berkeley-style "pseudo out-of-band data" which
  12071.     happens any time the user hits ^C twice.
  12072.     The latter is *very* common, as shown by an 'rlogin -x -d'
  12073.     using the CNS V4 rlogin.         Mark EIchin 1/95
  12074.     */
  12075.     debug(F110,"krb4_des_read",
  12076.           "about to call net_read() this will block",
  12077.           0
  12078.           );
  12079.     do {
  12080.         cc = net_read(fd, &c, 1);
  12081.         debug(F111,"net_read","chars read",cc);
  12082.         if (cc <= 0) {
  12083.             netclos();
  12084.             return(-1);
  12085.         }
  12086.         if (cc != 1) return 0; /* read error */
  12087.         if (cc == 1) {
  12088.             if (c == 0) gotzero = 1;
  12089.         }
  12090.     } while (!gotzero);
  12091.  
  12092.     debug(F110,"krb4_des_read","gotzero",0);
  12093.     cc = net_read(fd, &c, 1);
  12094.     debug(F111,"net_read","chars read",cc);
  12095.     if (cc < 0) {
  12096.         netclos();
  12097.         return(-1);
  12098.     } else if ( cc != 1 )
  12099.         return(0);
  12100.     net_len = c;
  12101.     cc = net_read(fd, &c, 1);
  12102.     debug(F111,"net_read","chars read",cc);
  12103.     if (cc < 0) {
  12104.         netclos();
  12105.         return(-1);
  12106.     } else if ( cc != 1 )
  12107.         return(0);
  12108.     net_len = (net_len << 8) | c;
  12109.     debug(F111,"net_read","chars read",cc);
  12110.     cc = net_read(fd, &c, 1);
  12111.     if (cc < 0) {
  12112.         netclos();
  12113.         return(-1);
  12114.     } else if ( cc != 1 )
  12115.         return(0);
  12116.     net_len = (net_len << 8) | c;
  12117.     debug(F111,"krb4_des_read","net_len",net_len);
  12118.  
  12119.     /* Note: net_len is unsigned */
  12120.     if (net_len > sizeof(des_inbuf)) {
  12121.         /* XXX preposterous length, probably out of sync.
  12122.         act as if pipe closed */
  12123.         return(0);
  12124.     }
  12125.     /* the writer tells us how much real data we are getting, but
  12126.     we need to read the pad bytes (8-byte boundary) */
  12127. #ifndef roundup
  12128. #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
  12129. #endif /* roundup */
  12130.     rd_len = roundup(net_len, 8);
  12131.     debug(F111,"krb4_des_read","rd_len",rd_len);
  12132.     cc = net_read(fd, des_inbuf, rd_len);
  12133.     debug(F111,"net_read","chars read",cc);
  12134.     if (cc < 0) {
  12135.         netclos();
  12136.         return(-1);
  12137.     } else if ( cc != rd_len )
  12138.         return(0);
  12139.  
  12140.     ckhexdump("krb4_des_read des_inbuf",des_inbuf,8);
  12141. #ifdef CK_ENCRYPTION
  12142. #ifdef KRB524
  12143.     (void) des_pcbc_encrypt(des_inbuf,
  12144.                              storage,
  12145.                              (net_len < 8) ? 8 : net_len,
  12146.                              k4_sched,
  12147.                              cred.session,
  12148.                              DECRYPT);
  12149. #else /* KRB524 */
  12150.     (void) des_pcbc_encrypt((Block *)des_inbuf,
  12151.                              (Block *)storage,
  12152.                              (net_len < 8) ? 8 : net_len,
  12153.                              k4_sched,
  12154.                              &cred.session,
  12155.                              DECRYPT);
  12156. #endif /* KRB524 */
  12157. #endif /* ENCRYPTION */
  12158.     ckhexdump("krb4_des_read storage",storage,8);
  12159.  
  12160.     /*
  12161.     * when the cleartext block is < 8 bytes, it is "right-justified"
  12162.     * in the block, so we need to adjust the pointer to the data
  12163.     */
  12164.     if (net_len < 8)
  12165.         store_ptr = storage + 8 - net_len;
  12166.     else
  12167.         store_ptr = storage;
  12168.     nstored = net_len;
  12169.  
  12170.     if ( !buf )
  12171.         return(0);
  12172.  
  12173.     if (nstored > len) {
  12174.         memcpy(buf, store_ptr, len);            /* safe */
  12175.         nreturned += len;
  12176.         store_ptr += len;
  12177.         nstored -= len;
  12178.     } else {
  12179.         memcpy(buf, store_ptr, nstored);        /* safe */
  12180.         nreturned += nstored;
  12181.         nstored = 0;
  12182.     }
  12183.  
  12184.     debug(F111,"net_read","nreturned",nreturned);
  12185.     return(nreturned);
  12186. }
  12187.  
  12188. int
  12189. krb4_des_write(fd, buf, len)
  12190. int fd;
  12191. char *buf;
  12192. int len;
  12193. {
  12194.     static char garbage_buf[8];
  12195.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  12196.     int cc;
  12197.  
  12198.     debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
  12199.     if ( !rlog_encrypt ) {
  12200.         cc = net_write(fd, buf, len);
  12201.         debug(F111,"net_write","chars written",cc);
  12202.         return(cc);
  12203.     }
  12204.  
  12205.     /*
  12206.     * pcbc_encrypt outputs in 8-byte (64 bit) increments
  12207.     *
  12208.     * it zero-fills the cleartext to 8-byte padding,
  12209.     * so if we have cleartext of < 8 bytes, we want
  12210.     * to insert random garbage before it so that the ciphertext
  12211.     * differs for each transmission of the same cleartext.
  12212.     * if len < 8 - sizeof(long), sizeof(long) bytes of random
  12213.     * garbage should be sufficient; leave the rest as-is in the buffer.
  12214.     * if len > 8 - sizeof(long), just garbage fill the rest.
  12215.     */
  12216.     if (len < 8) {
  12217.         random_confounder(8 - len, garbage_buf);
  12218.         /* this "right-justifies" the data in the buffer */
  12219.         (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
  12220.         ckhexdump("krb4_des_write garbage_buf",garbage_buf,8);
  12221.     } else
  12222.         ckhexdump("krb4_des_write buf",buf,8);
  12223. #ifdef CK_ENCRYPTION
  12224. #ifdef KRB524
  12225.     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
  12226.                              des_outpkt+4,
  12227.                              (len < 8) ? 8 : len,
  12228.                              k4_sched,
  12229.                              cred.session,
  12230.                              ENCRYPT);
  12231. #else /* KRB524 */
  12232.     (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
  12233.                              (Block *)(des_outpkt+4),
  12234.                              (len < 8) ? 8 : len,
  12235.                              k4_sched,
  12236.                              &cred.session,
  12237.                              ENCRYPT);
  12238. #endif /* KRB524 */
  12239. #endif /* ENCRYPTION */
  12240.     if ( len < 8 )
  12241.         ckhexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
  12242.     else
  12243.         ckhexdump("krb4_des_write (post pcbc) buf",buf,8);
  12244.     ckhexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
  12245.  
  12246.     /* tell the other end the real amount, but send an 8-byte padded
  12247.     packet */
  12248.     len_buf[0] = (len & 0xff000000) >> 24;
  12249.     len_buf[1] = (len & 0xff0000) >> 16;
  12250.     len_buf[2] = (len & 0xff00) >> 8;
  12251.     len_buf[3] = (len & 0xff);
  12252.     ckhexdump("krb4_des_write des_outpkt len",des_outpkt,12);
  12253.     cc = net_write(fd, des_outpkt, roundup(len,8)+4);
  12254.     debug(F111,"net_write","chars written",cc);
  12255.     return(len);
  12256. }
  12257. #endif /* KRB4 */
  12258. #endif /* RLOGCODE */
  12259.  
  12260. #ifdef KRB524
  12261. #ifndef OS2
  12262. /* The following functions are missing from the compatibility library */
  12263. const char *
  12264. krb_get_err_text_entry(r) int r;
  12265. {
  12266.     extern char krb_err_text[];
  12267.     return(krb_err_txt[r]);
  12268. }
  12269. #endif /* OS2 */
  12270. #endif /* KRB524 */
  12271. #endif /* CK_KERBEROS */
  12272.  
  12273. #ifdef CK_KERBEROS
  12274. #ifdef KRB5_U2U
  12275. /* Kerberos 5 User to User Client */
  12276. int
  12277. k5_user_to_user_client_auth()
  12278. {
  12279.     extern int ttyfd;
  12280.     register int retval, i;
  12281.     char **srealms;             /* realm(s) of server */
  12282.     char *princ;                /* principal in credentials cache */
  12283.     krb5_ccache cc;
  12284.     krb5_creds creds, *new_creds;
  12285.     krb5_data reply, msg, msgtext, princ_data;
  12286.     krb5_ticket * ticket = NULL;
  12287.  
  12288.     if (retval = k5_get_ccache(k5_context,&cc,NULL))
  12289.     {
  12290.         com_err("uu-client", retval, "getting credentials cache");
  12291.         return(-1);
  12292.     }
  12293.  
  12294.     memset ((char*)&creds, 0, sizeof(creds));
  12295.     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
  12296.     {
  12297.         com_err("uu-client", retval, "getting principal name");
  12298.         return(-1);
  12299.     }
  12300.  
  12301.     if (retval = krb5_get_host_realm(k5_context, szHostName, &srealms))
  12302.     {
  12303.         com_err("uu-client", retval, "getting realms for \"%s\"", szHostName);
  12304.         return(-1);
  12305.     }
  12306.  
  12307.     if (retval = krb5_build_principal_ext(k5_context, &creds.server,
  12308.                                           krb5_princ_realm(k5_context,
  12309.                                                          creds.client)->length,
  12310.                                           krb5_princ_realm(k5_context,
  12311.                                                          creds.client)->data,
  12312.                                           6, "krbtgt",
  12313.                                           krb5_princ_realm(k5_context,
  12314.                                                          creds.client)->length,
  12315.                                           krb5_princ_realm(k5_context,
  12316.                                                          creds.client)->data,
  12317.                                           0))
  12318.     {
  12319.         com_err("uu-client", retval, "setting up tgt server name");
  12320.         return(-1);
  12321.     }
  12322.  
  12323.     /* Get TGT from credentials cache */
  12324.     if (retval = krb5_get_credentials(k5_context, KRB5_GC_CACHED, cc,
  12325.                                        &creds, &new_creds))
  12326.     {
  12327.         com_err("uu-client", retval, "getting TGT");
  12328.         return(-1);
  12329.     }
  12330.  
  12331.     if (retval = krb5_unparse_name(k5_context, creds.client, &princ)) {
  12332.         com_err("uu-client", retval, "printing principal name");
  12333.         return(-1);
  12334.     }
  12335.     i = strlen(princ) + 1;
  12336.     princ_data.data = princ;
  12337.     princ_data.length = i;              /* include null terminator for
  12338.                                            server's convenience */
  12339.     retval = krb5_write_message(k5_context,
  12340.                                 (krb5_pointer) &ttyfd, &princ_data);
  12341.     if (retval)
  12342.     {
  12343.         com_err("uu-client", retval, "sending principal name to server");
  12344.         return(-1);
  12345.     }
  12346.     krb5_free_unparsed_name(k5_context,princ);
  12347.  
  12348.     retval = krb5_write_message(k5_context,
  12349.                                 (krb5_pointer) &ttyfd, &new_creds->ticket);
  12350.     if (retval)
  12351.     {
  12352.         com_err("uu-client", retval, "sending ticket to server");
  12353.         return(-1);
  12354.     }
  12355.  
  12356.     retval = krb5_read_message(k5_context, (krb5_pointer) &ttyfd, &reply);
  12357.     if (retval)
  12358.     {
  12359.         com_err("uu-client", retval, "reading reply from server");
  12360.         return(-1);
  12361.     }
  12362.  
  12363.     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
  12364.         com_err("uu-client", retval, "initializing the auth_context");
  12365.         return(-1);
  12366.     }
  12367.  
  12368.     if (!krb5_d_no_addresses) {
  12369.       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  12370.                         KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
  12371.                         KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
  12372.         com_err("uu-client", retval, "generating addrs for auth_context");
  12373.         return(-1);
  12374.       }
  12375.     }
  12376.  
  12377.     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
  12378.                                         KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
  12379.         com_err("uu-client", retval, "initializing the auth_context flags");
  12380.         return(-1);
  12381.     }
  12382.  
  12383.     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
  12384.                                               &new_creds->keyblock)) {
  12385.         com_err("uu-client", retval, "setting useruserkey for authcontext");
  12386.         return(-1);
  12387.     }
  12388.  
  12389.     /* read the ap_req to get the session key */
  12390.     retval = krb5_rd_req(k5_context, &auth_context, &reply,
  12391.                           NULL, NULL, NULL, &ticket);
  12392.     if (retval) {
  12393.         com_err("uu-client", retval, "reading AP_REQ from server");
  12394.         return(-1);
  12395.     }
  12396.  
  12397.     if (k5_u2u_read_msg(k5_context,&msg) < 0)
  12398.         return(-1);
  12399.  
  12400.     if ( strcmp("Kermit implements Kerberos 5 User to User",msg.data) )
  12401.         return(-1);
  12402.     krb5_free_data_contents(k5_context,&msg);
  12403.  
  12404.     msgtext.data = "As do I! :-)";
  12405.     msgtext.length = strlen(msgtext.data)+1;
  12406.  
  12407.     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
  12408.         return(-1);
  12409.  
  12410.     if (retval = krb5_unparse_name(k5_context,
  12411. #ifdef HEIMDAL
  12412.                                     ticket->client,
  12413. #else /* HEIMDAL */
  12414.                                     ticket->enc_part2->client,
  12415. #endif /* HEIMDAL */
  12416.                                     &princ))
  12417.         com_err("uu-client", retval, "while unparsing client name");
  12418.     else {
  12419.         ckstrncpy(szUserNameAuthenticated,princ,UIDBUFLEN);
  12420.         validUser = AUTH_VALID;
  12421.         authentication_version = AUTHTYPE_KERBEROS_V5;
  12422.         if ( !quiet )
  12423.             printf("Peer name is \"%s\"\n", princ);
  12424.         krb5_free_unparsed_name(k5_context,princ);
  12425.     }
  12426.     return 0;
  12427. }
  12428.  
  12429. /* Kerberos 5 User to User Server */
  12430.  
  12431. int
  12432. k5_user_to_user_server_auth()
  12433. {
  12434.     krb5_data pname_data, tkt_data;
  12435.     int retval;
  12436.     krb5_creds creds, *new_creds;
  12437.     krb5_ccache cc;
  12438.     krb5_data msg, msgtext;
  12439.     extern int ttyfd;
  12440.  
  12441.     if (retval = krb5_read_message(k5_context,
  12442.                                    (krb5_pointer) &ttyfd, &pname_data)) {
  12443.         com_err ("uu-server", retval, "reading pname");
  12444.         return(-1);
  12445.     }
  12446.     /* client sends it already null-terminated. */
  12447.     if ( !quiet )
  12448.         printf ("Peer name is \"%s\".\n", pname_data.data);
  12449.     ckstrncpy(szUserNameAuthenticated,pname_data.data,UIDBUFLEN);
  12450.     validUser = AUTH_VALID;
  12451.     authentication_version = AUTHTYPE_KERBEROS_V5;
  12452.  
  12453.     if (retval = krb5_read_message(k5_context,
  12454.                                    (krb5_pointer) &ttyfd, &tkt_data)) {
  12455.         com_err ("uu-server", retval, "reading ticket data");
  12456.         return(-1);
  12457.     }
  12458.  
  12459.     if (retval = k5_get_ccache(k5_context,&cc,NULL))
  12460.     {
  12461.         com_err("uu-server", retval, "getting credentials cache");
  12462.         return(-1);
  12463.     }
  12464.  
  12465.     memset ((char*)&creds, 0, sizeof(creds));
  12466.     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
  12467.     {
  12468.         com_err("uu-server", retval, "getting principal name");
  12469.         return(-1);
  12470.     }
  12471.  
  12472.     if (retval = krb5_parse_name(k5_context, pname_data.data, &creds.server))
  12473.     {
  12474.         com_err("uu-server", retval, "parsing client name");
  12475.         return(-1);
  12476.     }
  12477.     creds.second_ticket = tkt_data;
  12478.  
  12479.     if (retval = krb5_get_credentials(k5_context, KRB5_GC_USER_USER,
  12480.                                        cc, &creds, &new_creds))
  12481.     {
  12482.         com_err("uu-server", retval, "getting user-user ticket");
  12483.         return(-1);
  12484.     }
  12485.  
  12486.     /* send a ticket/authenticator to the other side, so it can get the key
  12487.        we're using for the krb_safe below. */
  12488.  
  12489.     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
  12490.         com_err("uu-server", retval, "making auth_context");
  12491.         return(-1);
  12492.     }
  12493.  
  12494.     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
  12495.                                          KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
  12496.         com_err("uu-server", retval, "initializing the auth_context flags");
  12497.         return(-1);
  12498.     }
  12499.  
  12500.     if (!krb5_d_no_addresses) {
  12501.       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  12502.                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
  12503.                                 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
  12504.         com_err("uu-server", retval, "generating addrs for auth_context");
  12505.         return(-1);
  12506.       }
  12507.     }
  12508.  
  12509.     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
  12510.                                               &new_creds->keyblock)) {
  12511.         com_err("uu-server", retval, "setting useruserkey for authcontext");
  12512.         return(-1);
  12513.     }
  12514.  
  12515.     if (retval = krb5_mk_req_extended(k5_context, &auth_context,
  12516.                                       AP_OPTS_USE_SESSION_KEY |
  12517.                                       AP_OPTS_MUTUAL_REQUIRED,
  12518.                                       NULL, new_creds, &msg)) {
  12519.         com_err("uu-server", retval, "making AP_REQ");
  12520.         return(-1);
  12521.     }
  12522.     retval = krb5_write_message(k5_context, (krb5_pointer) &ttyfd, &msg);
  12523.     if (retval) {
  12524.         com_err("uu-server", retval, "writing message to client");
  12525.         return(-1);
  12526.     }
  12527.     krb5_free_data_contents(k5_context,&msg);
  12528.  
  12529.     msgtext.data = "Kermit implements Kerberos 5 User to User";
  12530.     msgtext.length = strlen(msgtext.data)+1;
  12531.  
  12532.     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
  12533.         return(-1);
  12534.  
  12535.     if (k5_u2u_read_msg(k5_context,&msg) < 0)
  12536.         return(-1);
  12537.  
  12538.     if ( strcmp("As do I! :-)",msg.data) )
  12539.         return(-1);
  12540.     krb5_free_data_contents(k5_context,&msg);
  12541.  
  12542.  
  12543.     return(0);
  12544. }
  12545.  
  12546. int
  12547. k5_u2u_read_msg(krb5_context context, int fd, krb5_data * msg)
  12548. {
  12549.     int retval;
  12550.     krb5_data reply;
  12551.  
  12552.     retval = krb5_read_message(context, (krb5_pointer) &fd, &reply);
  12553.     if (retval)
  12554.     {
  12555.         com_err("uu-client", retval, "reading reply");
  12556.         return(-1);
  12557.     }
  12558.  
  12559.     if (retval = krb5_rd_priv(context, auth_context, &reply, msg, NULL)) {
  12560.         com_err("uu-client", retval, "decoding reply");
  12561.         return(-1);
  12562.     }
  12563.     return(0);
  12564. }
  12565.  
  12566. int
  12567. k5_u2u_write_msg(krb5_context context, int fd, krb5_data * msgtext)
  12568. {
  12569.     int retval;
  12570.     krb5_data msg;
  12571.  
  12572.     if (retval = krb5_mk_priv(k5_context, auth_context, msgtext, &msg, NULL))
  12573.     {
  12574.         com_err("uu-server", retval, "encoding message");
  12575.         return(-1);
  12576.     }
  12577.  
  12578.     retval = krb5_write_message(k5_context, (krb5_pointer) &fd, &msg);
  12579.     krb5_free_data_contents(k5_context,&msg);
  12580.     if (retval)
  12581.     {
  12582.         com_err("uu-server", retval, "writing message");
  12583.         return(-1);
  12584.     }
  12585.     return(0);
  12586. }
  12587.  
  12588. int
  12589. krb5_u2u_avail(fd)
  12590.     int fd;
  12591. {
  12592.     return(nstored);
  12593. }
  12594.  
  12595. int
  12596. krb5_u2u_read(fd, buf, len)
  12597.      int fd;
  12598.      register char *buf;
  12599.      int len;
  12600. {
  12601.     int nreturned = 0;
  12602.     krb5_data msg;
  12603.  
  12604.     debug(F111,"krb5_u2u_read","len",len);
  12605.  
  12606.     if ( !buf )
  12607.         return(0);
  12608.  
  12609.     if (nstored >= len) {
  12610.         memcpy(buf, store_ptr, len);        /* safe */
  12611.         store_ptr += len;
  12612.         nstored -= len;
  12613.         return(len);
  12614.     } else if (nstored) {
  12615.         memcpy(buf, store_ptr, nstored);    /* safe */
  12616.         nreturned += nstored;
  12617.         buf += nstored;
  12618.         len -= nstored;
  12619.         nstored = 0;
  12620.     }
  12621.  
  12622.     if (k5_u2u_read_msg(k5_context, fd, &msg) < 0)
  12623.         return(-1);
  12624.  
  12625.     if ( msg.length <= len ) {
  12626.         memcpy(buf, msg.data, msg.length);
  12627.         nreturned += msg.length;
  12628.         nstored = 0;
  12629.     } else {
  12630.         memcpy(buf, msg.data, len);
  12631.         nreturned += len;
  12632.  
  12633.         if ( msg.length - len < sizeof(storage) ) {
  12634.             store_ptr = storage;
  12635.             nstored = msg.length - len;
  12636.             memcpy(storage,msg.data+len,nstored);
  12637.         } else {
  12638.             nstored = 0;
  12639.             return(-1);
  12640.         }
  12641.     }
  12642.     return(nreturned);
  12643. }
  12644.  
  12645. int
  12646. krb5_u2u_write(fd, buf, len)
  12647.      int fd;
  12648.      char *buf;
  12649.      int len;
  12650. {
  12651.     krb5_data msg;
  12652.  
  12653.     msg.length = len;
  12654.     msg.data = buf;
  12655.  
  12656.     if ( k5_u2u_write_msg(k5_context, fd, &msg) < 0 )
  12657.         return(-1);
  12658.     else
  12659.         return(len);
  12660. }
  12661.  
  12662. #endif /* KRB5_U2U */
  12663. #endif /* CK_KERBEROS */
  12664.  
  12665. #ifdef CK_FORWARD_X
  12666. /*
  12667.  
  12668. Copyright (c) 1988  X Consortium
  12669.  
  12670. Permission is hereby granted, free of charge, to any person obtaining a copy
  12671. of this software and associated documentation files (the "Software"), to deal
  12672. in the Software without restriction, including without limitation the rights
  12673. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12674. copies of the Software, and to permit persons to whom the Software is
  12675. furnished to do so, subject to the following conditions:
  12676.  
  12677. The above copyright notice and this permission notice shall be included in
  12678. all copies or substantial portions of the Software.
  12679.  
  12680. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12681. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12682. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  12683. X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  12684. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  12685. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  12686.  
  12687. Except as contained in this notice, the name of the X Consortium shall not be
  12688. used in advertising or otherwise to promote the sale, use or other dealings
  12689. in this Software without prior written authorization from the X Consortium.
  12690.  
  12691. */
  12692. /*  Modified for stand-alone compiling by
  12693.  *  Peter 'Luna' Runestig <peter@runestig.com>
  12694.  */
  12695.  
  12696. #include <stdlib.h>
  12697. #include <string.h>
  12698. #include <fcntl.h>
  12699. #include <sys/stat.h>
  12700. #include <time.h>
  12701. #define Time_t time_t
  12702.  
  12703. void
  12704. XauDisposeAuth (auth)
  12705. Xauth   *auth;
  12706. {
  12707.     if (auth) {
  12708.         if (auth->address) (void) free (auth->address);
  12709.         if (auth->number) (void) free (auth->number);
  12710.         if (auth->name) (void) free (auth->name);
  12711.         if (auth->data) {
  12712.             (void) bzero (auth->data, auth->data_length);
  12713.             (void) free (auth->data);
  12714.         }
  12715.         free ((char *) auth);
  12716.     }
  12717.     return;
  12718. }
  12719.  
  12720. char *
  12721. XauFileName ()
  12722. {
  12723.     char *slashDotXauthority = "/.Xauthority";
  12724.     char    *name;
  12725.     static char *buf=NULL;
  12726.     static int  bsize=0;
  12727.     int     size, namelen;
  12728.     extern char * tn_fwdx_xauthority;
  12729.  
  12730.     if ( tn_fwdx_xauthority )
  12731.         return(tn_fwdx_xauthority);
  12732.  
  12733.     if (name = getenv ("XAUTHORITY"))
  12734.         return(name);
  12735.     name = zhome();
  12736.     if ( !name )
  12737.         return(NULL);
  12738.     namelen = strlen (name);
  12739.     size = namelen + strlen(slashDotXauthority) + 1;
  12740.     if (size > bsize) {
  12741.         if (buf)
  12742.             free (buf);
  12743.         buf = malloc ((unsigned) size);
  12744.         if (!buf)
  12745.             return 0;
  12746.         bsize = size;
  12747.     }
  12748.     ckstrncpy (buf, name, bsize);
  12749.     if ( name[namelen-1] != '/'
  12750. #ifdef OS2
  12751.          && name[namelen-1] != '\\'
  12752. #endif /* OS2 */
  12753.          )
  12754.         ckstrncat (buf, slashDotXauthority, bsize);
  12755.     else
  12756.         ckstrncat (buf, &slashDotXauthority[1], bsize);
  12757.     return(buf);
  12758. }
  12759.  
  12760. static int
  12761. binaryEqual (a, b, len)
  12762. register char   *a, *b;
  12763. register int    len;
  12764. {
  12765.     while (len--)
  12766.         if (*a++ != *b++)
  12767.             return 0;
  12768.     return 1;
  12769. }
  12770.  
  12771. #ifndef R_OK
  12772. #define R_OK 04
  12773. #endif /* R_OK */
  12774.  
  12775. Xauth *
  12776. XauGetAuthByAddr (family, address_length, address,
  12777.                           number_length, number,
  12778.                           name_length, name)
  12779. unsigned int    family;
  12780. unsigned int    address_length;
  12781. const char      *address;
  12782. unsigned int    number_length;
  12783. const char      *number;
  12784. unsigned int    name_length;
  12785. const char      *name;
  12786. {
  12787.     FILE    *auth_file;
  12788.     char    *auth_name;
  12789.     Xauth   *entry;
  12790.  
  12791.     auth_name = XauFileName();
  12792.     if (!auth_name)
  12793.         return 0;
  12794.     if (access (auth_name, R_OK) != 0)          /* checks REAL id */
  12795.         return 0;
  12796.     auth_file = fopen (auth_name, "rb");
  12797.     if (!auth_file)
  12798.         return 0;
  12799.     for (;;) {
  12800.         entry = XauReadAuth (auth_file);
  12801.         if (!entry)
  12802.             break;
  12803.         /*
  12804.          * Match when:
  12805.          *   either family or entry->family are FamilyWild or
  12806.          *    family and entry->family are the same
  12807.          *  and
  12808.          *   either address or entry->address are empty or
  12809.          *    address and entry->address are the same
  12810.          *  and
  12811.          *   either number or entry->number are empty or
  12812.          *    number and entry->number are the same
  12813.          *  and
  12814.          *   either name or entry->name are empty or
  12815.          *    name and entry->name are the same
  12816.          */
  12817.  
  12818. /*      if ((family == FamilyWild || entry->family == FamilyWild ||
  12819.              (entry->family == family &&
  12820.               address_length == entry->address_length &&
  12821.               binaryEqual (entry->address, address, (int)address_length))) &&
  12822.             (number_length == 0 || entry->number_length == 0 ||
  12823.              (number_length == entry->number_length &&
  12824.               binaryEqual (entry->number, number, (int)number_length))) &&
  12825.             (name_length == 0 || entry->name_length == 0 ||
  12826.              (entry->name_length == name_length &&
  12827.               binaryEqual (entry->name, name, (int)name_length)))) */
  12828.         /* the original matching code above doesn't seem to meet the matching
  12829.          * algorithm, it doesn't check if "address_length == 0 ||
  12830.          * entry->address_length == 0". / Luna 2000-02-09
  12831.          */
  12832.         if ((family == FamilyWild || entry->family == FamilyWild ||
  12833.               entry->family == family) &&
  12834.             (address_length == 0 || entry->address_length == 0 ||
  12835.               (address_length == entry->address_length &&
  12836.               binaryEqual (entry->address, address, (int)address_length))) &&
  12837.             (number_length == 0 || entry->number_length == 0 ||
  12838.              (number_length == entry->number_length &&
  12839.               binaryEqual (entry->number, number, (int)number_length))) &&
  12840.             (name_length == 0 || entry->name_length == 0 ||
  12841.              (entry->name_length == name_length &&
  12842.               binaryEqual (entry->name, name, (int)name_length))))
  12843.             break;
  12844.         XauDisposeAuth (entry);
  12845.     }
  12846.     (void) fclose (auth_file);
  12847.     return entry;
  12848. }
  12849.  
  12850. static int
  12851. read_short (shortp, file)
  12852. unsigned short  *shortp;
  12853. FILE            *file;
  12854. {
  12855.     unsigned char   file_short[2];
  12856.  
  12857.     if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
  12858.         return 0;
  12859.     *shortp = file_short[0] * 256 + file_short[1];
  12860.     return 1;
  12861. }
  12862.  
  12863. static int
  12864. read_counted_string (countp, stringp, file)
  12865. unsigned short  *countp;
  12866. char    **stringp;
  12867. FILE    *file;
  12868. {
  12869.     unsigned short  len;
  12870.     char            *data;
  12871.  
  12872.     if (read_short (&len, file) == 0)
  12873.         return 0;
  12874.     if (len == 0) {
  12875.         data = 0;
  12876.     } else {
  12877.         data = malloc ((unsigned) len);
  12878.         if (!data)
  12879.             return 0;
  12880.         if (fread (data, (int) sizeof (char), (int) len, file) != len) {
  12881.             bzero (data, len);
  12882.             free (data);
  12883.             return 0;
  12884.         }
  12885.     }
  12886.     *stringp = data;
  12887.     *countp = len;
  12888.     return 1;
  12889. }
  12890.  
  12891. Xauth *
  12892. XauReadAuth (auth_file)
  12893. FILE    *auth_file;
  12894. {
  12895.     Xauth   local;
  12896.     Xauth   *ret;
  12897.  
  12898.     if (read_short (&local.family, auth_file) == 0)
  12899.         return 0;
  12900.     if (read_counted_string (&local.address_length,
  12901.                              &local.address, auth_file) == 0)
  12902.         return 0;
  12903.     if (read_counted_string (&local.number_length,
  12904.                              &local.number, auth_file) == 0) {
  12905.         if (local.address) free (local.address);
  12906.         return 0;
  12907.     }
  12908.     if (read_counted_string (&local.name_length,
  12909.                              &local.name, auth_file) == 0) {
  12910.         if (local.address) free (local.address);
  12911.         if (local.number) free (local.number);
  12912.         return 0;
  12913.     }
  12914.     if (read_counted_string (&local.data_length,
  12915.                              &local.data, auth_file) == 0) {
  12916.         if (local.address) free (local.address);
  12917.         if (local.number) free (local.number);
  12918.         if (local.name) free (local.name);
  12919.         return 0;
  12920.     }
  12921.     ret = (Xauth *) malloc (sizeof (Xauth));
  12922.     if (!ret) {
  12923.         if (local.address) free (local.address);
  12924.         if (local.number) free (local.number);
  12925.         if (local.name) free (local.name);
  12926.         if (local.data) {
  12927.             bzero (local.data, local.data_length);
  12928.             free (local.data);
  12929.         }
  12930.         return 0;
  12931.     }
  12932.     *ret = local;
  12933.     return ret;
  12934. }
  12935.  
  12936. static int
  12937. write_short (s, file)
  12938. unsigned short  s;
  12939. FILE            *file;
  12940. {
  12941.     unsigned char   file_short[2];
  12942.  
  12943.     file_short[0] = (s & (unsigned)0xff00) >> 8;
  12944.     file_short[1] = s & 0xff;
  12945.     if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
  12946.         return 0;
  12947.     return 1;
  12948. }
  12949.  
  12950. static int
  12951. write_counted_string (count, string, file)
  12952. unsigned short  count;
  12953. char    *string;
  12954. FILE    *file;
  12955. {
  12956.     if (write_short (count, file) == 0)
  12957.         return 0;
  12958.     if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
  12959.         return 0;
  12960.     return 1;
  12961. }
  12962.  
  12963. int
  12964. XauWriteAuth (auth_file, auth)
  12965. FILE    *auth_file;
  12966. Xauth   *auth;
  12967. {
  12968.     if (write_short (auth->family, auth_file) == 0)
  12969.         return 0;
  12970.     if (write_counted_string (auth->address_length,
  12971.                               auth->address, auth_file) == 0)
  12972.         return 0;
  12973.     if (write_counted_string (auth->number_length,
  12974.                               auth->number, auth_file) == 0)
  12975.         return 0;
  12976.     if (write_counted_string (auth->name_length, auth->name, auth_file) == 0)
  12977.         return 0;
  12978.     if (write_counted_string (auth->data_length, auth->data, auth_file) == 0)
  12979.         return 0;
  12980.     return 1;
  12981. }
  12982.  
  12983. #ifdef KRB5
  12984. #ifdef K5_XAUTH
  12985. /*
  12986.  * functions to encode/decode Kerberos V5 principals
  12987.  * into something that can be reasonable spewed over
  12988.  * the wire
  12989.  *
  12990.  * Author: Tom Yu <tlyu@MIT.EDU>
  12991.  *
  12992.  * Still needs to be fixed up wrt signed/unsigned lengths, but we'll worry
  12993.  * about that later.
  12994.  */
  12995.  
  12996. /*
  12997.  * XauKrb5Encode
  12998.  *
  12999.  * this function encodes the principal passed to it in a format that can
  13000.  * easily be dealt with by stuffing it into an X packet.  Encoding is as
  13001.  * follows:
  13002.  *   length count of the realm name
  13003.  *   realm
  13004.  *   component count
  13005.  *   length of component
  13006.  *   actual principal component
  13007.  *   etc....
  13008.  *
  13009.  * Note that this function allocates a hunk of memory, which must be
  13010.  * freed to avoid nasty memory leak type things.  All counts are
  13011.  * byte-swapped if needed. (except for the total length returned)
  13012.  *
  13013.  * nevermind.... stuffing the encoded packet in net byte order just to
  13014.  * always do the right thing.  Don't have to frob with alignment that way.
  13015.  */
  13016. int
  13017. XauKrb5Encode(princ, outbuf)
  13018.     krb5_principal princ;       /* principal to encode */
  13019.     krb5_data *outbuf;          /* output buffer */
  13020. {
  13021.     CARD16 i, numparts, totlen = 0, plen, rlen;
  13022.     char *cp, *pdata;
  13023.  
  13024.     rlen = krb5_princ_realm(princ)->length;
  13025.     numparts = krb5_princ_size(princ);
  13026.     totlen = 2 + rlen + 2;      /* include room for realm length
  13027.                                    and component count */
  13028.     for (i = 0; i < numparts; i++)
  13029.         totlen += krb5_princ_component(princ, i)->length + 2;
  13030.     /* add 2 bytes each time for length */
  13031.     if ((outbuf->data = (char *)malloc(totlen)) == NULL)
  13032.         return -1;
  13033.     cp = outbuf->data;
  13034.     *cp++ = (char)((int)(0xff00 & rlen) >> 8);
  13035.     *cp++ = (char)(0x00ff & rlen);
  13036.     memcpy(cp, krb5_princ_realm(princ)->data, rlen);    /* safe */
  13037.     cp += rlen;
  13038.     *cp++ = (char)((int)(0xff00 & numparts) >> 8);
  13039.     *cp++ = (char)(0x00ff & numparts);
  13040.     for (i = 0; i < numparts; i++)
  13041.     {
  13042.         plen = krb5_princ_component(princ, i)->length;
  13043.         pdata = krb5_princ_component(princ, i)->data;
  13044.         *cp++ = (char)((int)(0xff00 & plen) >> 8);
  13045.         *cp++ = (char)(0x00ff & plen);
  13046.         memcpy(cp, pdata, plen);                        /* safe */
  13047.         cp += plen;
  13048.     }
  13049.     outbuf->length = totlen;
  13050.     return 0;
  13051. }
  13052.  
  13053. /*
  13054.  * XauKrb5Decode
  13055.  *
  13056.  * This function essentially reverses what XauKrb5Encode does.
  13057.  * return value: 0 if okay, -1 if malloc fails, -2 if inbuf format bad
  13058.  */
  13059. int
  13060. XauKrb5Decode(inbuf, princ)
  13061.     krb5_data inbuf;
  13062.     krb5_principal *princ;
  13063. {
  13064.     CARD16 i, numparts, plen, rlen;
  13065.     CARD8 *cp, *pdata;
  13066.  
  13067.     if (inbuf.length < 4)
  13068.     {
  13069.         return -2;
  13070.     }
  13071.     *princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
  13072.     if (*princ == NULL)
  13073.         return -1;
  13074.     bzero(*princ, sizeof (krb5_principal_data));
  13075.     cp = (CARD8 *)inbuf.data;
  13076.     rlen = *cp++ << 8;
  13077.     rlen |= *cp++;
  13078.     if (inbuf.length < 4 + (int)rlen + 2)
  13079.     {
  13080.         krb5_free_principal(*princ);
  13081.         return -2;
  13082.     }
  13083.     krb5_princ_realm(*princ)->data = (char *)malloc(rlen);
  13084.     if (krb5_princ_realm(*princ)->data == NULL)
  13085.     {
  13086.         krb5_free_principal(*princ);
  13087.         return -1;
  13088.     }
  13089.     krb5_princ_realm(*princ)->length = rlen;
  13090.     memcpy(krb5_princ_realm(*princ)->data, cp, rlen);   /* safe */
  13091.     cp += rlen;
  13092.     numparts = *cp++ << 8;
  13093.     numparts |= *cp++;
  13094.     krb5_princ_name(*princ) =
  13095.         (krb5_data *)malloc(numparts * sizeof (krb5_data));
  13096.     if (krb5_princ_name(*princ) == NULL)
  13097.     {
  13098.         krb5_free_principal(*princ);
  13099.         return -1;
  13100.     }
  13101.     krb5_princ_size(*princ) = 0;
  13102.     for (i = 0; i < numparts; i++)
  13103.     {
  13104.         if (cp + 2 > (CARD8 *)inbuf.data + inbuf.length)
  13105.         {
  13106.             krb5_free_principal(*princ);
  13107.             return -2;
  13108.         }
  13109.         plen = *cp++ << 8;
  13110.         plen |= *cp++;
  13111.         if (cp + plen > (CARD8 *)inbuf.data + inbuf.length)
  13112.         {
  13113.             krb5_free_principal(*princ);
  13114.             return -2;
  13115.         }
  13116.         pdata = (CARD8 *)malloc(plen);
  13117.         if (pdata == NULL)
  13118.         {
  13119.             krb5_free_principal(*princ);
  13120.             return -1;
  13121.         }
  13122.         krb5_princ_component(*princ, i)->data = (char *)pdata;
  13123.         krb5_princ_component(*princ, i)->length = plen;
  13124.         memcpy(pdata, cp, plen);        /* safe */
  13125.         cp += plen;
  13126.         krb5_princ_size(*princ)++;
  13127.     }
  13128.     return 0;
  13129. }
  13130. #endif /* K5_XAUTH */
  13131. #endif /* KRB5 */
  13132. #endif /* CK_FORWARD_X */
  13133. #endif /* CK_AUTHENTICATION */
  13134.  
  13135. /* C K _ A U T H _ I N I T
  13136.  * Initialize the Kerberos system for a pending connection
  13137.  *   hostname - a reverse DNS lookup of the hostname when possible
  13138.  *   ipaddr   - the ip address of the host
  13139.  *   username - the name the user wants to connect under not necessarily
  13140.  *              the same as principal
  13141.  *   socket   - the socket handle (ttyfd in Kermit speak)
  13142.  *
  13143.  * Returns: 1 on success and 0 on failure
  13144.  */
  13145.  
  13146. int
  13147. #ifdef CK_ANSIC
  13148. ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
  13149. #else /* CK_ANSIC */
  13150. ck_auth_init( hostname, ipaddr, username, socket )
  13151.     char * hostname; char * ipaddr; char *username; int socket;
  13152. #endif /* CK_ANSIC */
  13153. {
  13154. #ifdef CK_AUTHENTICATION
  13155. #ifdef OS2
  13156.     if ( !ck_security_loaddll() ) {
  13157.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  13158.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  13159.         return(0);
  13160.     }
  13161. #endif /* OS2 */
  13162. #endif /* CK_AUTHENTICAITON */
  13163. #ifdef CK_ENCRYPTION
  13164.     if ( !!ck_crypt_is_installed() ) {
  13165.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  13166.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  13167.     }
  13168. #endif /* CK_ENCRYPTION */
  13169.  
  13170.     if (!hostname) hostname = "";
  13171.     if (!ipaddr) ipaddr = "";
  13172.     if (!username) username = "";
  13173.  
  13174.     debug(F110,"ck_auth_init Username",username,0);
  13175.     debug(F110,"ck_auth_init Hostname",hostname,0);
  13176.     debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
  13177.  
  13178.     ckstrncpy( szUserName, username, UIDBUFLEN );
  13179.     ckstrncpy( szHostName, hostname, UIDBUFLEN );
  13180.     ckstrncpy( szIP, ipaddr, 16 );
  13181.     szUserNameRequested[0] = '\0';
  13182.     szUserNameAuthenticated[0] = '\0';
  13183.     validUser = AUTH_REJECT;
  13184.     accept_complete = 0;
  13185.     authentication_version = AUTHTYPE_NULL;
  13186.  
  13187. #ifdef CK_AUTHENTICATION
  13188.     auth_how = 0;
  13189.     auth_crypt = 0;
  13190.     auth_fwd = 0;
  13191.     mutual_complete = 0;
  13192.     if ( sstelnet )
  13193.         str_data[3] = TELQUAL_REPLY;
  13194.     else
  13195.         str_data[3] = TELQUAL_IS;
  13196. #endif /* CK_AUTHENTICATION */
  13197.  
  13198. #ifdef CK_SRP
  13199.     srp_waitresp = 0;
  13200. #endif /* SRP */
  13201.  
  13202. #ifdef CK_KERBEROS
  13203. #ifdef KRB5
  13204.     /* free previous ret_cred  */
  13205.     if ( ret_cred ) {
  13206. #ifdef CK_ENCRYPTION
  13207. #ifdef HEIMDAL
  13208.         if ( k5_session_key == &ret_cred->session)
  13209.             k5_session_key = NULL;
  13210. #else /* HEIMDAL */
  13211.         if ( k5_session_key == &ret_cred->keyblock)
  13212.             k5_session_key = NULL;
  13213. #endif /* HEIMDAL */
  13214. #endif /* CK_ENCRYPTION */
  13215.         krb5_free_creds(k5_context, ret_cred);
  13216.         ret_cred = NULL;
  13217.     }
  13218.     if (k5_ticket) {
  13219.         krb5_free_ticket(k5_context, k5_ticket);
  13220.         k5_ticket = NULL;
  13221.     }
  13222.     /* and context */
  13223.     if ( k5_context ) {
  13224.         krb5_free_context(k5_context);
  13225.         k5_context = NULL;
  13226.     }
  13227.  
  13228.     /* create k5_context */
  13229.     krb5_init_context(&k5_context);
  13230. #ifndef MIT_CURRENT
  13231. #ifndef NO_KRB5_INIT_ETS
  13232. /* This routine is a no-op in Kerberos 1.4.x and later */
  13233. /* and in some installations it can't be found in which case */
  13234. /* define NO_KRB5_INIT_ETS */
  13235.     if (k5_context)
  13236.         krb5_init_ets(k5_context);
  13237. #endif    /* NO_KRB5_INIT_ETS */
  13238. #endif /* MIT_CURRENT */
  13239. #ifdef KRB524_CONV
  13240.     krb524_init_ets(k5_context);
  13241. #endif /* KRB524_CONV */
  13242.     memset(&k5_auth,0,sizeof(k5_auth));
  13243.     if (auth_context) {
  13244.         krb5_auth_con_free(k5_context, auth_context);
  13245.         auth_context = 0;
  13246.     }
  13247. #ifdef CK_ENCRYPTION
  13248.     if (k5_session_key) {
  13249.         krb5_free_keyblock(k5_context, k5_session_key);
  13250.         k5_session_key = 0;
  13251.     }
  13252. #endif /* ENCRYPTION */
  13253. #ifdef TLS_VERIFY
  13254.     krb5_tls_verified = 0;
  13255. #endif /* TLS_VERIFY */
  13256. #endif /* KRB5 */
  13257.  
  13258. #ifdef KRB4
  13259. #ifdef CK_ENCRYPTION
  13260.     /* Initialize buffers used for authentication */
  13261.     memset(&k4_session_key, 0, sizeof(k4_session_key));
  13262.     memset(&k4_challenge, 0, sizeof(k4_challenge));
  13263. #endif /* CK_ENCRYPTION */
  13264. #endif /* KRB4 */
  13265.  
  13266. #ifdef RLOGCODE
  13267.     rlog_encrypt = 0;
  13268. #endif /* RLOGCODE */
  13269.     nstored = 0;
  13270.     store_ptr = storage;
  13271.     memset(storage,0,sizeof(storage));
  13272. #endif /* CK_KERBEROS */
  13273.  
  13274. #ifdef CK_ENCRYPTION
  13275.     kstream_destroy();
  13276.     if (!kstream_create_from_fd(socket, NULL))
  13277.         return(0);
  13278. #endif /* CK_ENCRYPTION */
  13279.     return(1);
  13280. }
  13281.  
  13282. void
  13283. auth_finished(result) int result; {
  13284.     extern char uidbuf[];
  13285.     extern int sstelnet;
  13286.  
  13287.     validUser = result;
  13288.     switch (result) {
  13289.     case AUTH_REJECT:           /* Rejected */
  13290.         if (sstelnet)
  13291.             uidbuf[0] = '\0';
  13292.         authentication_version = AUTHTYPE_NULL;
  13293.         break;
  13294.     case AUTH_UNKNOWN:          /* We don't know who he is, but he's okay */
  13295.         if (sstelnet)
  13296.             strcpy(uidbuf,"(unknown)");
  13297.         break;
  13298.     case AUTH_OTHER:            /* We know him, but not his name */
  13299.         if (sstelnet)
  13300.             strcpy(uidbuf,"(other)");
  13301.         break;
  13302.     case AUTH_USER:             /* We know he name */
  13303.     case AUTH_VALID:            /* We know him, and he needs no password */
  13304.         if (sstelnet)
  13305.             strcpy(uidbuf,szUserNameRequested);
  13306.         break;
  13307.     }
  13308. }
  13309.  
  13310. #ifdef MACOSX
  13311. #ifdef KRB5
  13312.  
  13313. krb5_error_code
  13314. ck_krb5_write_message(krb5_context con, krb5_pointer ptr, krb5_data *data)
  13315. {
  13316.     int fd = *((int *)ptr);
  13317.     long msglen;
  13318.  
  13319.     msglen = htonl(data->length);
  13320.     if (net_write(fd,(CHAR *)&msglen,4) != 4) {
  13321.         return(-1);
  13322.     }
  13323.     if ( data->length ) {
  13324.         if (net_write(fd,data->data,data->length) != data->length) {
  13325.             return(-1);
  13326.         }
  13327.     }
  13328.     return(0);
  13329. }
  13330.  
  13331. krb5_error_code
  13332. ck_krb5_read_message( krb5_context context,
  13333.                       krb5_pointer ptr,
  13334.                       krb5_data * data)
  13335. {
  13336.     extern int ttyfd;
  13337.     int fd = *((int *)ptr);
  13338.     long msglen;
  13339.     char *p;
  13340.     int i, rc;
  13341.  
  13342.     if (net_read(fd,&msglen,4) < 0)
  13343.         return(-1);
  13344.  
  13345.     data->length = ntohl(msglen);
  13346.     if ( data->length ) {
  13347.         data->data = malloc(data->length);
  13348.  
  13349.         i = 0;
  13350.         while ( i < data->length ) {
  13351.             if ((rc = net_read(fd,&data->data[i],(data->length - i))) < 0)
  13352.                 return(-1);
  13353.             i += rc;
  13354.         }
  13355.     }
  13356.     return(0);
  13357. }
  13358. #endif /* KRB5 */
  13359. #endif /* MACOSX */
  13360. #endif /* CK_SECURITY */
  13361.  
  13362.  
  13363.