home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckv200.zip / ckuath.c < prev    next >
C/C++ Source or Header  |  2001-12-03  |  398KB  |  12,892 lines

  1. char *ckathv = "Authentication, 8.0.204, 2 Dec 2001";
  2. /*
  3.   C K U A T H . C  --  Authentication for C-Kermit
  4.  
  5.   Copyright (C) 1999,2001,
  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@columbia.edu)
  11. */
  12. /*
  13.  * Additional copyrights included with affected code.
  14.  */
  15.  
  16. #ifdef HEIMDAL
  17. /*
  18.   Turned off User to User support
  19.   Turned off KDESTROY support
  20.   Turned off KLIST support
  21.   Turned off krb5_prompter() support
  22.   Turned off ticket validation
  23.   Turned off ticket renewal
  24.   Turned off alternative cache support in k5_get_ccache()
  25.  
  26.   Remaining link problems:
  27.  
  28.   ckuath.o: In function `ck_krb5_initTGT':
  29.   ckuath.o(.text+0x50c2): undefined reference to `krb5_string_to_deltat'
  30.   ckuath.o(.text+0x516d): undefined reference to `krb5_string_to_deltat'
  31.   ckuath.o(.text+0x51ef): undefined reference to `krb5_string_to_deltat'
  32. */
  33. #endif /* HEIMDAL */
  34.  
  35. /*
  36.  * Implements Kerberos 4/5, SRP, SSL, NTLM authentication and START_TLS
  37.  */
  38.  
  39. #include "ckcsym.h"
  40. #include "ckcdeb.h"
  41.  
  42. #ifdef CK_AUTHENTICATION
  43. #define CKUATH_C
  44.  
  45. #include "ckcker.h"
  46. #include "ckucmd.h"                             /* For struct keytab */
  47. #include "ckcnet.h"
  48. #include "ckctel.h"
  49.  
  50. #ifdef CK_SSL
  51. #ifdef KRB5
  52. #define TLS_VERIFY
  53. #endif /* KRB5 */
  54. #endif /* CK_SSL */
  55.  
  56. #ifdef CK_DES
  57. #ifdef CK_SSL
  58. #ifndef LIBDES
  59. #define LIBDES
  60. #endif /* LIBDES */
  61. #endif /* CK_SSL */
  62. #endif /* CK_DES */
  63.  
  64. #ifdef CRYPT_DLL
  65. #ifndef LIBDES
  66. #define LIBDES
  67. #endif /* LIBDES */
  68. #ifdef OS2
  69. #ifdef NT
  70. #include <windows.h>
  71. #else /* NT */
  72. #define INCL_DOSMODULEMGR
  73. #include <os2.h>
  74. #endif /* NT */
  75. #endif /* OS2 */
  76. #endif /* CRYPT_DLL */
  77.  
  78. #ifdef NT
  79. #define KRB5_AUTOCONF__
  80. #define NTLM
  81. #endif /* NT */
  82.  
  83. #ifdef CK_KERBEROS
  84. #define KINIT
  85. #ifndef HEIMDAL
  86. #define KLIST
  87. #define KDESTROY
  88. #endif /* HEIMDAL */
  89. #define CHECKADDRS
  90. #else /* CK_KERBEROS */
  91. #ifdef KRB4
  92. #undef KRB4
  93. #endif /* KRB4 */
  94. #ifdef KRB5
  95. #undef KRB5
  96. #endif /* KRB5 */
  97. #ifdef KRB524
  98. #undef KRB524
  99. #endif /* KRB524 */
  100. #endif /* CK_KERBEROS */
  101.  
  102. #include <stdlib.h>
  103. #include <string.h>
  104. #include <stdio.h>
  105. #include <time.h>
  106. #include <fcntl.h>
  107. #include <malloc.h>
  108. #ifdef OS2
  109. #include <io.h>
  110. #endif /* OS2 */
  111.  
  112. #ifdef KRB5
  113. #ifdef HEIMDAL
  114. #ifdef printf
  115. #define saveprintf printf
  116. #undef printf
  117. #endif /* printf */
  118. #include "krb5.h"
  119. #include "com_err.h"
  120. #ifdef saveprintf
  121. #define printf saveprintf
  122. #endif /* saveprintf */
  123. #else /* HEIMDAL */
  124. #include "krb5.h"
  125. #include "profile.h"
  126. #include "com_err.h"
  127. #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
  128. #define KRB5_HAVE_GET_INIT_CREDS
  129. #else
  130. #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val))
  131. #endif
  132. #ifndef KRB5_HAVE_GET_INIT_CREDS
  133. #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data)
  134. #endif
  135. #endif /* HEIMDAL */
  136. #ifdef HAVE_PWD_H
  137. #include <pwd.h>
  138. #endif
  139. #endif /* KRB5 */
  140.  
  141. #ifdef KRB4
  142. #define  des_cblock Block
  143. #define  des_key_schedule Schedule
  144. #ifdef KRB524
  145. #ifdef NT
  146. #define _WINDOWS
  147. #endif /* NT */
  148. #include "kerberosIV/krb.h"
  149. #ifndef OS2
  150. _PROTOTYP(const char * krb_get_err_text_entry, (int));
  151. #endif /* OS2 */
  152. #else /* KRB524 */
  153. #ifdef SOLARIS
  154. #ifndef sun
  155. /* for some reason the Makefile entries for the Solaris systems have -Usun */
  156. #define sun
  157. #endif /* sun */
  158. #endif /* SOLARIS */
  159. #include "krb.h"
  160. #define krb_get_err_text_entry krb_get_err_text
  161. #endif /* KRB524 */
  162. #else /* KRB4 */
  163. #ifdef CK_SSL
  164. #define  des_cblock Block
  165. #define  des_key_schedule Schedule
  166. #endif /* CK_SSL */
  167. #endif /* KRB4 */
  168.  
  169. #include "ckuath.h"
  170. #ifdef CK_KERBEROS
  171. #ifndef KRB5
  172. #define NOBLOCKDEF
  173. #else /* KRB5 */
  174. #ifdef KRB524
  175. #define NOBLOCKDEF
  176. #endif /* KRB524 */
  177. #endif /* KRB5 */
  178. #endif /* CK_KERBEROS */
  179. #include "ckuat2.h"
  180.  
  181. #ifdef CK_SSL
  182. #ifdef LIBDES
  183. #ifndef HEADER_DES_H
  184. #define HEADER_DES_H
  185. #endif /* HEADER_DES_H */
  186. #endif /* LIBDES */
  187. #include "ck_ssl.h"
  188. extern int ssl_finished_messages;
  189. #endif /* SSL */
  190.  
  191. #define PWD_SZ 128
  192.  
  193. #ifndef LIBDES
  194. #ifdef UNIX
  195. #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
  196. #endif /* UNIX */
  197. #else /* LIBDES */
  198. #define des_fixup_key_parity des_set_odd_parity
  199. #endif /* LIBDES */
  200.  
  201. #ifdef OS2
  202. #define MAP_DES
  203. #ifdef KRB4
  204. #define MAP_KRB4
  205. #endif /* KRB4 */
  206. #ifdef SRPDLL
  207. #define MAP_SRP
  208. #endif /* SRPDLL */
  209. #ifdef KRB5
  210. #define MAP_KRB5
  211. #endif /* KRB5 */
  212. #ifdef CRYPT_DLL
  213. #define MAP_CRYPT
  214. #endif /* CRYPT_DLL */
  215. #define MAP_NTLM
  216. #include "ckoath.h"
  217. #endif /* OS2 */
  218.  
  219. /*
  220.  * Globals
  221.  */
  222. int authentication_version = AUTHTYPE_NULL;
  223. int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
  224. int auth_how=0;
  225. int auth_crypt=0;
  226. int auth_fwd=0;
  227.  
  228. /* These are state completion variables */
  229. int accept_complete = 0;
  230. static int mutual_complete = 0;
  231.  
  232. #ifdef KRB4
  233. #ifdef OS2
  234. static LEASH_CREDENTIALS cred;
  235. #else /* OS2 */
  236. static CREDENTIALS cred;
  237. #endif /* OS2 */
  238. static KTEXT_ST k4_auth;
  239. static char     k4_name[ANAME_SZ];
  240. static AUTH_DAT k4_adat  = { 0 };
  241. static MSG_DAT  k4_msg_data;
  242. #ifdef CK_ENCRYPTION
  243. static Block    k4_session_key     = { 0 };
  244. static Schedule k4_sched;
  245. static Block    k4_challenge       = { 0 };
  246. #ifdef MIT_CURRENT
  247. static krb5_keyblock k4_krbkey;
  248. #endif /* MIT_CURRENT */
  249. #endif /* ENCRYPTION */
  250. #define KRB4_SERVICE_NAME    "rcmd"
  251.  
  252. _PROTOTYP(static int k4_auth_send,(VOID));
  253. _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
  254. _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
  255. #endif /* KRB4 */
  256.  
  257. #ifdef KRB5
  258. static krb5_data          k5_auth;
  259. static krb5_auth_context  auth_context;
  260. static krb5_keyblock     *k5_session_key = NULL;
  261. static krb5_ticket       *k5_ticket = NULL;
  262. #ifndef KRB5_SERVICE_NAME
  263. #define KRB5_SERVICE_NAME    "host"
  264. #endif
  265.  
  266. _PROTOTYP(static int k5_auth_send,(int,int,int));
  267. _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
  268. _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
  269. _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
  270. #ifdef TLS_VERIFY
  271. static int krb5_tls_verified = 0;
  272. #endif /* TLS_VERIFY */
  273. #endif /* KRB5 */
  274.  
  275. #ifdef GSSAPI_KRB5
  276. #include <gssapi/gssapi.h>
  277. #include <gssapi/gssapi_generic.h>
  278. #include <gssapi/gssapi_krb5.h>
  279.  
  280. static gss_ctx_id_t gcontext;
  281. #define GSS_BUFSIZ 4096
  282. static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr;
  283. static char gss_stbuf[GSS_BUFSIZ];
  284. static gss_name_t gss_target_name;
  285. static struct gss_channel_bindings_struct gss_chan;
  286.  
  287. _PROTOTYP(static int gssk5_auth_send,(int,int,int));
  288. _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int));
  289. _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int));
  290. _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int));
  291. #endif /* GSSAPI_KRB5 */
  292.  
  293. #ifdef CK_SRP
  294. #ifdef PRE_SRP_1_7_3
  295. _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
  296. _PROTOTYP(static int srp_is,(int, unsigned char *, int));
  297. #else /* PRE_SRP_1_7_3 */
  298. _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int));
  299. _PROTOTYP(static int new_srp_is,(int, unsigned char *, int));
  300. #endif /* PRE_SRP_1_7_3 */
  301. #endif /* SRP */
  302.  
  303. _PROTOTYP(void auth_finished, (int));
  304.  
  305. #ifdef CK_ENCRYPTION
  306. int encrypt_flag = 1;
  307. #endif
  308. #ifdef FORWARD
  309. int forward_flag = 0;              /* forward tickets? */
  310. int forwardable_flag = 1;          /* get forwardable tickets to forward? */
  311. int forwarded_tickets = 0;         /* were tickets forwarded? */
  312. #endif
  313.  
  314. static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  315.                       AUTHTYPE_KERBEROS_V5, };
  316. #define AUTHTMPBL 2048
  317. static char strTmp[AUTHTMPBL+1];
  318.        char szUserNameRequested[UIDBUFLEN+1];    /* for incoming connections */
  319.        char szUserNameAuthenticated[UIDBUFLEN+1];/* for incoming connections */
  320.        char szHostName[UIDBUFLEN+1];
  321. static char szLocalHostName[UIDBUFLEN+1];
  322. static char szIP[16];
  323. #ifndef OS2
  324. static
  325. #endif /* OS2 */
  326.        char szUserName[UIDBUFLEN+1];
  327. static int  validUser = AUTH_REJECT;    /* User starts out invalid */
  328.  
  329. static struct kstream_crypt_ctl_block ctl;
  330. static kstream g_kstream=NULL;
  331.  
  332. #ifdef KRB5
  333. krb5_context k5_context=NULL;
  334. static krb5_creds * ret_cred=NULL;
  335. static krb5_context telnet_context=NULL;
  336. static char * telnet_krb5_realm = NULL;
  337. static krb5_principal fwd_server = NULL;
  338. #endif /* KRB5 */
  339.  
  340. #ifdef CK_SRP
  341. #ifdef PRE_SRP_1_4_4
  342. #ifndef PRE_SRP_1_4_5
  343. #define PRE_SRP_1_4_5
  344. #endif /* PRE_SRP_1_4_5 */
  345. #endif /* PRE_SRP_1_4_5 */
  346. #ifdef PRE_SRP_1_4_5
  347. #ifndef PRE_SRP_1_7_3
  348. #define PRE_SRP_1_7_3
  349. #endif /* PRE_SRP_1_7_3 */
  350. #endif /* PRE_SRP_1_4_5 */
  351. #include <t_pwd.h>
  352. #include <t_client.h>
  353. #include <t_server.h>
  354. static struct t_server * ts = NULL;
  355. static struct t_client * tc = NULL;
  356. #ifdef PRE_SRP_1_4_4
  357. static struct t_pw * tpw = NULL;
  358. static struct t_conf * tconf = NULL;
  359. #endif /* PRE_SRP_1_4_4 */
  360. #ifndef PRE_SRP_1_7_3
  361. #ifndef STDC_HEADERS
  362. #define STDC_HEADERS 1
  363. #endif /* STDC_HEADERS */
  364. #include <srp.h>
  365. static SRP * s_srp = NULL;
  366. static cstr * s_key = NULL;
  367. static SRP * c_srp = NULL;
  368. static cstr * c_key = NULL;
  369. #endif /* PRE_SRP_1_7_3 */
  370. static int srp_waitresp = 0;    /* Flag to indicate readiness for response */
  371. static char srp_passwd[PWD_SZ];
  372. #endif /* CK_SRP */
  373.  
  374. #ifdef CK_KERBEROS
  375. #ifdef RLOGCODE
  376. #define OPTS_FORWARD_CREDS           0x00000020
  377. #define OPTS_FORWARDABLE_CREDS       0x00000010
  378. #define KCMD_KEYUSAGE                1026
  379.  
  380. #define RLOG_BUFSIZ 5120
  381. static int rlog_encrypt = 0;
  382. char des_inbuf[2*RLOG_BUFSIZ];       /* needs to be > largest read size */
  383. char des_outpkt[2*RLOG_BUFSIZ+4];    /* needs to be > largest write size */
  384. #ifdef KRB5
  385. krb5_data desinbuf,desoutbuf;
  386. krb5_encrypt_block eblock;             /* eblock for encrypt/decrypt */
  387. static krb5_data encivec_i, encivec_o;
  388. #endif /* KRB5 */
  389. #endif /* RLOGCODE */
  390. static char storage[65536];            /* storage for the decryption */
  391. static int nstored = 0;
  392. static char *store_ptr = storage;
  393.  
  394. extern char * krb5_d_principal;        /* Default principal */
  395. extern char * krb5_d_instance;          /* Default instance */
  396. extern char * krb5_d_realm;        /* Default realm */
  397. extern char * krb5_d_cc;        /* Default credentials cache */
  398. extern char * krb5_d_srv;               /* Default service name */
  399. extern int    krb5_d_lifetime;          /* Default lifetime */
  400. extern int    krb5_d_forwardable;
  401. extern int    krb5_d_proxiable;
  402. extern int    krb5_d_renewable;
  403. extern int    krb5_autoget;
  404. extern int    krb5_checkaddrs;
  405. extern int    krb5_d_getk4;
  406. extern int    krb5_d_no_addresses;
  407. extern char * k5_keytab;
  408.  
  409. extern int    krb5_errno;
  410. extern char * krb5_errmsg;
  411.  
  412. extern char * krb4_d_principal;        /* Default principal */
  413. extern char * krb4_d_realm;        /* Default realm */
  414. extern char * krb4_d_srv;               /* Default service name */
  415. extern int    krb4_d_lifetime;          /* Default lifetime */
  416. extern int    krb4_d_preauth;
  417. extern char * krb4_d_instance;
  418. extern int    krb4_autoget;
  419. extern int    krb4_checkaddrs;
  420. extern char * k4_keytab;
  421.  
  422. extern int    krb4_errno;
  423. extern char * krb4_errmsg;
  424. #endif /* CK_KERBEROS */
  425.  
  426. extern char tn_msg[], hexbuf[];         /* from ckcnet.c */
  427. extern char pwbuf[];
  428. extern int  pwflg, pwcrypt;
  429. extern int deblog, debses, tn_deb;
  430. extern int sstelnet, inserver;
  431. #ifdef CK_LOGIN
  432. extern int ckxanon;
  433. #endif /* CK_LOGIN */
  434. extern int tn_auth_how;
  435. extern int tn_auth_enc;
  436. #ifdef CK_ENCRYPTION
  437. extern int cx_type;
  438. #endif /* CK_ENCRYPTION */
  439. extern int quiet, ttyfd;
  440.  
  441. int
  442. ck_gssapi_is_installed()
  443. {
  444. #ifdef KRB5
  445. #ifdef OS2
  446.     return(hGSSAPI != NULL);
  447. #else /* OS2 */
  448.     return(1);
  449. #endif /* OS2 */
  450. #else /* KRB5 */
  451.     return(0);
  452. #endif /* KRB5 */
  453. }
  454.  
  455. int
  456. ck_krb5_is_installed()
  457. {
  458. #ifdef KRB5
  459. #ifdef OS2
  460.     return(hKRB5_32 != NULL);
  461. #else /* OS2 */
  462.     return(1);
  463. #endif /* OS2 */
  464. #else /* KRB5 */
  465.     return(0);
  466. #endif /* KRB5 */
  467. }
  468.  
  469.  
  470. int
  471. ck_krb5_is_installed_as_server()
  472. {
  473. #ifdef KRB5
  474. #ifdef HEIMDAL
  475.     krb5_error_code ret;
  476.     krb5_keytab kt;
  477.     krb5_kt_cursor cursor;
  478.  
  479.     ret = krb5_kt_default(k5_context, &kt);
  480.     if ( ret ) {
  481.         krb5_kt_close(k5_context, kt);
  482.         return(0);
  483.     } else {
  484.         krb5_kt_end_seq_get(k5_context, kt, &cursor);
  485.         krb5_kt_close(k5_context, kt);
  486.         return(1);
  487.     }
  488. #else /* HEIMDAL */
  489. #ifndef COMMENT
  490.     char ktname[CKMAXPATH]="";
  491.  
  492.     if ( k5_keytab ) {
  493.         ckstrncpy(ktname,k5_keytab,CKMAXPATH);
  494.     } else {
  495.         krb5_error_code code;
  496.  
  497.         if ( k5_context == NULL)
  498.             if (krb5_init_context(&k5_context))
  499.                 return(0);
  500.  
  501.         code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH);
  502.         debug(F101,"krb5_kt_default_name","",code);
  503.         if ( code ) {
  504.             /* We can't check the existence of the file since we can't   */
  505.             /* determine the file name.  So we return TRUE and let       */
  506.             /* Krb5 be offered to the user even though it may fail later */
  507.             return(1);
  508.         }
  509.     }
  510.  
  511.     if ( !strncmp("FILE:",ktname,5) ) {
  512.         if ( zchki(&ktname[5]) > 0 )
  513.             return(1);
  514.         else
  515.             return(0);
  516.     } else {
  517.         if (ktname[0])
  518.             return(1);
  519.     else
  520.             return(0);
  521.     }
  522. #else /* COMMENT */
  523.     krb5_error_code        krb5rc = KRB5KRB_ERR_GENERIC;
  524.     krb5_context        krb5context = NULL;
  525.     krb5_ccache         krb5ccdef = NULL;
  526.     krb5_creds                krb5creds, *krb5credsp = NULL;
  527.     int                         rc = 0;
  528.  
  529.     if ( !ck_krb5_is_installed() )
  530.         return(0);
  531.  
  532.     memset((char *)&krb5creds, 0, sizeof(krb5creds));
  533.  
  534.     if ((krb5rc = krb5_init_context(&krb5context)) != 0)
  535.         goto err;
  536.  
  537.     if ((krb5rc = krb5_sname_to_principal(krb5context,
  538.                       szHostName,
  539.                       krb5_d_srv ?
  540.                       krb5_d_srv :
  541.                       KRB5_SERVICE_NAME,
  542.                       KRB5_NT_SRV_HST,
  543.                       &krb5creds.server)) != 0)
  544.       goto err;
  545.  
  546.     if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
  547.         goto err;
  548.  
  549.     if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
  550.                                          &krb5creds.client)) != 0)
  551.         goto err;
  552.  
  553.     if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
  554.                                         &krb5creds, &krb5credsp)) != 0)
  555.         goto err;
  556.     rc = 1;
  557.  
  558.   err:
  559.  
  560.     if (krb5creds.client)
  561.       krb5_free_principal(krb5context, krb5creds.client);
  562.     if (krb5creds.server)
  563.       krb5_free_principal(krb5context, krb5creds.server);
  564.     if (krb5context)
  565.       krb5_free_context(krb5context);
  566.     return(rc);
  567.  
  568. #endif /* COMMENT */
  569. #endif /* HEIMDAL */
  570. #else /* KRB5 */
  571.     return(0);
  572. #endif /* KRB5 */
  573. }
  574.  
  575. int
  576. ck_krb4_is_installed()
  577. {
  578. #ifdef KRB4
  579. #ifdef OS2
  580.     return(hKRB4_32 != NULL);
  581. #else /* OS2 */
  582.     return(1);
  583. #endif /* OS2 */
  584. #else /* KRB4 */
  585.     return(0);
  586. #endif /* KRB4 */
  587. }
  588.  
  589. int
  590. ck_krb4_is_installed_as_server()
  591. {
  592.     if ( !ck_krb4_is_installed() )
  593.         return(0);
  594.  
  595. #ifdef KRB4
  596.     if ( !k4_keytab ) {
  597. #ifdef NT
  598.         char name[CKMAXPATH]="";
  599.         DWORD len = CKMAXPATH;
  600.  
  601.         len = GetWindowsDirectory(name,len);
  602.         if ( len > 0 )
  603.             ckstrncat(name,"/srvtab",CKMAXPATH);
  604.         if ( name[0] )
  605.             makestr(&k4_keytab,name);
  606. #else /* NT */
  607.         makestr(&k4_keytab,"/etc/srvtab");
  608. #endif /* NT */
  609.     }
  610.  
  611.     if ( !k4_keytab )
  612.         return(0);
  613.  
  614.     if ( zchki(k4_keytab) > 0 )
  615.         return(1);
  616. #ifdef KRB524
  617.     else if (ck_krb5_is_installed_as_server())
  618.         return(1);
  619. #endif /* KRB524 */
  620.     else
  621.         return(0);
  622. #endif /* KRB4 */
  623. }
  624.  
  625. int
  626. ck_srp_is_installed_as_server()
  627. {
  628. #ifdef CK_SRP
  629. #ifdef SRPDLL
  630.     if ( hSRP == NULL )
  631.         return(0);
  632. #endif /* SRPDLL */
  633. #ifndef PRE_SRP_1_7_3
  634.     {
  635.         SRP * s_srp = SRP_new(SRP_RFC2945_server_method());
  636.         if ( s_srp ) {
  637.             SRP_free(s_srp);
  638.             s_srp = NULL;
  639.             return(1);
  640.         }
  641.         return(0);
  642.     }
  643. #else /* PRE_SRP_1_7_3 */
  644.     {
  645.         struct t_pw * tpw = NULL;
  646.         struct t_conf * tconf = NULL;
  647.         if((tconf = t_openconf(NULL)) == NULL)
  648.             return(0);
  649.         if((tpw = t_openpw(NULL)) == NULL) {
  650.             t_closeconf(tconf);
  651.             return(0);
  652.         }
  653.         t_closeconf(tconf);
  654.         t_closepw(tpw);
  655.         return(1);
  656.     }
  657. #endif /* PRE_SRP_1_7_3 */
  658. #else /* SRP */
  659.     return(0);
  660. #endif /* SRP */
  661. }
  662.  
  663. int
  664. ck_srp_is_installed()
  665. {
  666. #ifdef CK_SRP
  667. #ifdef SRPDLL
  668.     if ( hSRP == NULL )
  669.         return(0);
  670. #endif /* SRPDLL */
  671.     return(1);
  672. #else /* CK_SRP */
  673.     return(0);
  674. #endif /* CK_SRP */
  675. }
  676.  
  677. int
  678. ck_krypto_is_installed()
  679. {
  680. #ifdef CK_SRP
  681. #ifdef OS2
  682.     if ( hLIBKRYPTO == NULL )
  683.         return(0);
  684. #endif /* OS2 */
  685.     return(1);
  686. #else /* CK_SRP */
  687.     return(0);
  688. #endif /* CK_SRP */
  689. }
  690.  
  691. int
  692. ck_crypt_is_installed()
  693. {
  694. #ifdef CK_ENCRYPTION
  695. #ifdef CRYPT_DLL
  696.     return(hCRYPT != NULL);
  697. #else /* CRYPT_DLL */
  698.     return(1);
  699. #endif /* CRYPT_DLL */
  700. #else /* ENCRYPTION */
  701.     return(0);
  702. #endif /* ENCRYPTION */
  703. }
  704.  
  705. int
  706. ck_ntlm_is_installed()
  707. {
  708. #ifdef NT
  709.     return(hSSPI != NULL);
  710. #else /* NT */
  711.     return(0);
  712. #endif /* NT */
  713. }
  714.  
  715. /* C K _ K R B _ I N I T
  716.  * Initialize the Kerberos system for a pending connection
  717.  *   hostname - a reverse DNS lookup of the hostname when possible
  718.  *   ipaddr   - the ip address of the host
  719.  *   username - the name the user wants to connect under not necessarily
  720.  *              the same as principal
  721.  *   socket   - the socket handle (ttyfd in Kermit speak)
  722.  *
  723.  * Returns: 1 on success and 0 on failure
  724.  */
  725.  
  726. int
  727. #ifdef CK_ANSIC
  728. ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
  729. #else /* CK_ANSIC */
  730. ck_auth_init( hostname, ipaddr, username, socket )
  731.     char * hostname; char * ipaddr; char *username; int socket;
  732. #endif /* CK_ANSIC */
  733. {
  734. #ifdef OS2
  735.     if ( !ck_security_loaddll() ) {
  736.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  737.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  738.         return(0);
  739.     }
  740. #endif /* OS2 */
  741.  
  742.     if ( !!ck_crypt_is_installed() ) {
  743.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  744.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  745.     }
  746.  
  747.     if (!hostname) hostname = "";
  748.     if (!ipaddr) ipaddr = "";
  749.     if (!username) username = "";
  750.  
  751.     ckstrncpy( szUserName, username, UIDBUFLEN );
  752.     ckstrncpy( szHostName, hostname, UIDBUFLEN );
  753.     ckstrncpy( szIP, ipaddr, 16 );
  754.     szUserNameRequested[0] = '\0';
  755.     szUserNameAuthenticated[0] = '\0';
  756.     validUser = AUTH_REJECT;
  757.  
  758.     if ( sstelnet )
  759.         str_data[3] = TELQUAL_REPLY;
  760.     else
  761.         str_data[3] = TELQUAL_IS;
  762.  
  763.     debug(F110,"ck_auth_init Username",username,0);
  764.     debug(F110,"ck_auth_init Hostname",hostname,0);
  765.     debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
  766.  
  767. #ifdef KRB5
  768.     /* free previous ret_cred  */
  769.     if ( ret_cred ) {
  770. #ifdef CK_ENCRYPTION
  771. #ifdef HEIMDAL
  772.     if ( k5_session_key == &ret_cred->session)
  773.         k5_session_key = NULL;
  774. #else /* HEIMDAL */
  775.     if ( k5_session_key == &ret_cred->keyblock)
  776.         k5_session_key = NULL;
  777. #endif /* HEIMDAL */
  778. #endif /* CK_ENCRYPTION */
  779.         krb5_free_creds(k5_context, ret_cred);
  780.         ret_cred = NULL;
  781.     }
  782.     if (k5_ticket) {
  783.         krb5_free_ticket(k5_context, k5_ticket);
  784.         k5_ticket = NULL;
  785.     }
  786.     /* and context */
  787.     if ( k5_context ) {
  788.         krb5_free_context(k5_context);
  789.         k5_context = NULL;
  790.     }
  791.  
  792.     /* create k5_context */
  793.     krb5_init_context(&k5_context);
  794. #ifndef MIT_CURRENT
  795.     if (k5_context)
  796.         krb5_init_ets(k5_context);
  797. #endif /* MIT_CURRENT */
  798.     memset(&k5_auth,0,sizeof(k5_auth));
  799.     if (auth_context) {
  800.         krb5_auth_con_free(k5_context, auth_context);
  801.         auth_context = 0;
  802.     }
  803. #ifdef CK_ENCRYPTION
  804.     if (k5_session_key) {
  805.         krb5_free_keyblock(k5_context, k5_session_key);
  806.         k5_session_key = 0;
  807.     }
  808. #endif /* ENCRYPTION */
  809. #ifdef TLS_VERIFY
  810.     krb5_tls_verified = 0;
  811. #endif /* TLS_VERIFY */
  812. #endif /* KRB5 */
  813.  
  814. #ifdef KRB4
  815. #ifdef CK_ENCRYPTION
  816.     /* Initialize buffers used for authentication */
  817.     memset(&k4_session_key, 0, sizeof(k4_session_key));
  818.     memset(&k4_challenge, 0, sizeof(k4_challenge));
  819. #endif /* ENCRYPTION */
  820. #endif /* KRB4 */
  821.  
  822.     kstream_destroy();
  823.  
  824.     auth_how = 0;
  825.     auth_crypt = 0;
  826.     auth_fwd = 0;
  827.     accept_complete = 0;
  828.     mutual_complete = 0;
  829.     authentication_version = AUTHTYPE_NULL;
  830.  
  831. #ifdef CK_KERBEROS
  832. #ifdef RLOGCODE
  833.     rlog_encrypt = 0;
  834. #endif /* RLOGCODE */
  835.     nstored = 0;
  836.     store_ptr = storage;
  837.     memset(storage,0,sizeof(storage));
  838. #endif /* CK_KERBEROS */
  839. #ifdef CK_SRP
  840.     srp_waitresp = 0;
  841. #endif /* SRP */
  842.  
  843.     /* create kstream from socket */
  844.     /* a kstream is simply a structure containing the socket handle */
  845.     /* and pointers to the appropriate functions for encryption,    */
  846.     /* decryption, and the like.                                    */
  847.     ctl.encrypt = auth_encrypt;
  848.     ctl.decrypt = auth_decrypt;
  849.     ctl.init = auth_init;
  850.     ctl.destroy = auth_destroy;
  851.  
  852.     if (!kstream_create_from_fd(socket, &ctl, NULL))
  853.         return(0);
  854.  
  855.     return(1);
  856. }
  857.  
  858. int
  859. ck_tn_auth_valid()
  860. {
  861.     return(validUser);
  862. }
  863.  
  864. /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
  865.  *
  866.  * Is an authentication negotiation still in progress?
  867.  *
  868.  */
  869.  
  870. int
  871. #ifdef CK_ANSIC
  872. ck_tn_auth_in_progress(void)
  873. #else
  874. ck_tn_auth_in_progress()
  875. #endif
  876. {
  877.     switch (authentication_version) {
  878.     case AUTHTYPE_AUTO:
  879.         return(1);
  880.     case AUTHTYPE_NULL:
  881.         return(0);
  882. #ifdef KRB4
  883.     case AUTHTYPE_KERBEROS_V4:
  884.         if (!accept_complete) {
  885.         debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
  886.            "",0);
  887.             return(1);
  888.     }
  889.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  890.         debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
  891.            "",0);
  892.             return(1);
  893.     }
  894.         else
  895.             return(0);
  896. #endif /* KRB4 */
  897. #ifdef KRB5
  898.     case AUTHTYPE_KERBEROS_V5:
  899.         if (!accept_complete) {
  900.         debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
  901.            "",0);
  902.             return(1);
  903.     }
  904.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  905.         debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
  906.            "",0);
  907.             return(1);
  908.     }
  909.         else
  910.             return(0);
  911. #ifdef GSSAPI_K5
  912.     case AUTHTYPE_GSSAPI_KRB5:
  913.         if (!accept_complete) {
  914.         debug(F100,"ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete",
  915.            "",0);
  916.             return(1);
  917.     }
  918.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  919.         debug(F100,"ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete",
  920.            "",0);
  921.             return(1);
  922.     }
  923.         else
  924.             return(0);
  925.         break;
  926. #endif /* GSSAPI_K5 */
  927. #endif /* KRB5 */
  928. #ifdef CK_SRP
  929.     case AUTHTYPE_SRP:
  930.         if (!accept_complete || srp_waitresp)
  931.             return(1);
  932.         else
  933.             return(0);
  934. #endif /* CK_SRP */
  935. #ifdef NTLM
  936.     case AUTHTYPE_NTLM:
  937.         if (!accept_complete) {
  938.         debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
  939.            "",0);
  940.             return(1);
  941.     }
  942.         else
  943.             return(0);
  944. #endif /* NTLM */
  945.     case AUTHTYPE_SSL:
  946.         if (!accept_complete) {
  947.         debug(F100,"ck_auth_in_progress() SSL !accept_complete",
  948.            "",0);
  949.             return(1);
  950.     }
  951.         else
  952.             return(0);
  953.     default:
  954.         return(0);
  955.     }
  956.     return(0);
  957. }
  958.  
  959.  
  960. /*  C K _ K R B _ T N _ A U T H _ R E Q U E S T
  961.  *
  962.  *  Builds a Telnet Authentication Send Negotiation providing the
  963.  *  list of supported authentication methods.  To be used only
  964.  *  when accepting incoming connections as only the server (DO) side of the
  965.  *  Telnet negotiation is allowed to send an AUTH SEND.
  966.  *
  967.  *  Returns: 0 on success and -1 on failure
  968.  */
  969.  
  970. static unsigned char str_request[64] = { IAC, SB,
  971.                                              TELOPT_AUTHENTICATION,
  972.                                              TELQUAL_SEND };
  973. #ifdef GSSAPI_K5
  974. static int
  975. ck_tn_auth_request_gsskrb5(int i)
  976. {
  977.     if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) {
  978.         if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
  979.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  980.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  981.                tn_auth_enc == TN_AUTH_ENC_EXCH) ) {
  982.             str_request[i++] = AUTHTYPE_KERBEROS_V5;
  983.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  984.             str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE;
  985.  
  986.             if ( deblog || tn_deb || debses )
  987.                 ckstrncat(tn_msg,
  988.                 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ",
  989.                           TN_MSG_LEN);
  990.             i++;
  991.         }
  992.     }
  993. }
  994. #endif /* GSSAPI_K5 */
  995.  
  996. #ifdef KRB5
  997. static int
  998. ck_tn_auth_request_krb5(int i)
  999. {
  1000.     if (ck_krb5_is_installed_as_server()) {
  1001. #ifdef CK_SSL
  1002.         if ( ck_ssleay_is_installed() &&
  1003.              (tls_active_flag || ssl_active_flag) &&
  1004.              ssl_finished_messages )
  1005.         {
  1006. #ifdef USE_INI_CRED_FWD
  1007.             if ( forward_flag &&
  1008.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1009.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1010.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1011.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  1012.                  )
  1013.             {
  1014.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1015.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1016.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  1017.                 str_request[i] |= INI_CRED_FWD_ON;
  1018.  
  1019.                 if ( deblog || tn_deb || debses )
  1020.                     ckstrncat(tn_msg,
  1021.  "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ",
  1022.                                TN_MSG_LEN);
  1023.                 i++;
  1024.             }
  1025. #endif /* USE_INI_CRED_FWD */
  1026.             if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
  1027.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1028.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1029.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  1030.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1031.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1032.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  1033.  
  1034.                 if ( deblog || tn_deb || debses )
  1035.                     ckstrncat(tn_msg,
  1036.               "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ",
  1037.                   TN_MSG_LEN);
  1038.                 i++;
  1039.             }
  1040.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1041.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1042.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1043.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1044.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  1045.  
  1046.                 if ( deblog || tn_deb || debses )
  1047.                     ckstrncat(tn_msg,
  1048.                     "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
  1049.                                TN_MSG_LEN);
  1050.                 i++;
  1051.             }
  1052.         }
  1053. #ifdef CK_ENCRYPTION
  1054.         else
  1055.         {
  1056. #endif /* CK_ENCRYPTION */
  1057. #endif /* CK_SSL */
  1058. #ifdef CK_ENCRYPTION
  1059. #ifdef USE_INI_CRED_FWD
  1060.             if ( forward_flag &&
  1061.                  TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1062.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1063.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1064.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1065.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1066.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  1067.                  )
  1068.             {
  1069.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1070.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1071.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1072.                 str_request[i] |= INI_CRED_FWD_ON;
  1073.  
  1074.                 if ( deblog || tn_deb || debses )
  1075.                     ckstrncat(tn_msg,
  1076.   "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ",
  1077.                                TN_MSG_LEN);
  1078.                 i++;
  1079.             }
  1080. #endif /* USE_INI_CRED_FWD */
  1081.  
  1082.             if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1083.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1084.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1085.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1086.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1087.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  1088.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1089.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1090.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1091.  
  1092.                 if ( deblog || tn_deb || debses )
  1093.                     ckstrncat(tn_msg,
  1094.               "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ",
  1095.                                TN_MSG_LEN);
  1096.                 i++;
  1097.             }
  1098. #ifdef CK_SSL
  1099.         }
  1100. #endif /* CK_SSL */
  1101. #endif /* CK_ENCRYPTION */
  1102.  
  1103.         if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1104.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1105.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1106.                tn_auth_enc == TN_AUTH_ENC_NONE)
  1107. #ifdef CK_SSL
  1108.              && !(ck_ssleay_is_installed() &&
  1109.                    (tls_active_flag || ssl_active_flag) &&
  1110.                    tls_is_anon(0))
  1111. #endif /* CK_SSL */
  1112.              )
  1113.         {
  1114. #ifdef CK_ENCRYPTION
  1115.             /* Can't perform mutual authentication without encryption */
  1116.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1117.                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1118.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1119.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1120.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1121.  
  1122.                 if ( deblog || tn_deb || debses )
  1123.                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ",
  1124.                                TN_MSG_LEN);
  1125.                 i++;
  1126.             }
  1127. #endif /* CK_ENCRYPTION */
  1128.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1129.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1130.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1131.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1132.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1133.  
  1134.                 if ( deblog || tn_deb || debses )
  1135.                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ",
  1136.                                TN_MSG_LEN);
  1137.                 i++;
  1138.             }
  1139.         }
  1140.     }
  1141.     return(i);
  1142. }
  1143. #endif /* KRB5 */
  1144. #ifdef KRB4
  1145. static int
  1146. ck_tn_auth_request_krb4(int i)
  1147. {
  1148.     if (ck_krb4_is_installed_as_server()) {
  1149. #ifdef CK_ENCRYPTION
  1150.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1151.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1152.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1153.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1154.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1155.                tn_auth_enc == TN_AUTH_ENC_TELOPT) )
  1156.         {
  1157.             str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1158.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1159.             str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1160.  
  1161.             if ( deblog || tn_deb || debses )
  1162.           ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ",
  1163.             TN_MSG_LEN);
  1164.             i++;
  1165.         }
  1166. #endif /* CK_ENCRYPTION */
  1167.  
  1168.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1169.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1170.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1171.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1172.         {
  1173. #ifdef CK_ENCRYPTION
  1174.             /* Can't perform mutual authentication without encryption */
  1175.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1176.                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1177.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1178.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1179.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1180.  
  1181.                 if ( deblog || tn_deb || debses )
  1182.                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ",
  1183.                                TN_MSG_LEN);
  1184.                 i++;
  1185.             }
  1186. #endif /* CK_ENCRYPTION */
  1187.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1188.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1189.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  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,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ",
  1195.                                TN_MSG_LEN);
  1196.                 i++;
  1197.             }
  1198.         }
  1199.     }
  1200.  
  1201.     return(i);
  1202. }
  1203. #endif /* KRB4 */
  1204.  
  1205. #ifdef CK_SRP
  1206. static int
  1207. ck_tn_auth_request_srp(int i)
  1208. {
  1209.     if (ck_srp_is_installed_as_server()) {
  1210. #ifndef PRE_SRP_1_4_5
  1211.         /* Dont' do this yet.  SRP when it uses the ENCRYPT_USING_TELOPT   */
  1212.         /* flag it must perform a checksum of the auth-type-pair but there */
  1213.         /* is no mechansim to do that yet.                                 */
  1214. #ifdef CK_SSL
  1215.         if ( ck_ssleay_is_installed() &&
  1216.              (tls_active_flag || ssl_active_flag) &&
  1217.              ssl_finished_messages &&
  1218.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1219.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1220.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1221.                    tn_auth_enc == TN_AUTH_ENC_TELOPT))
  1222.         {
  1223.             str_request[i++] = AUTHTYPE_SRP;
  1224.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1225.             str_request[i] |= AUTH_ENCRYPT_START_TLS;
  1226.  
  1227.             if ( deblog || tn_deb || debses )
  1228.                 ckstrncat(tn_msg,
  1229.                            "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
  1230.                            TN_MSG_LEN);
  1231.             i++;
  1232.         }
  1233. #ifdef CK_ENCRYPTION
  1234.         else {
  1235. #endif /* CK_ENCRYPTION */
  1236. #endif /* CK_SSL */
  1237. #ifdef CK_ENCRYPTION
  1238.             if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1239.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  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_TELOPT)
  1244.                  ) {
  1245.                 str_request[i++] = AUTHTYPE_SRP;
  1246.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1247.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1248.  
  1249.                 if ( deblog || tn_deb || debses )
  1250.                     ckstrncat(tn_msg,
  1251.                     "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ",
  1252.                                TN_MSG_LEN);
  1253.                 i++;
  1254.             }
  1255. #ifdef CK_SSL
  1256.         }
  1257. #endif /* CK_SSL */
  1258. #endif /* CK_ENCRYPTION */
  1259. #endif /* PRE_SRP_1_4_5 */
  1260.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1261.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1262.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1263.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1264.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1265.                tn_auth_enc == TN_AUTH_ENC_NONE)
  1266. #ifdef CK_SSL
  1267.              && !(ck_ssleay_is_installed() &&
  1268.                    (tls_active_flag || ssl_active_flag) &&
  1269.                    tls_is_anon(0))
  1270. #endif /* CK_SSL */
  1271.              )
  1272.         {
  1273.             str_request[i++] = AUTHTYPE_SRP;
  1274.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1275.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1276.  
  1277.             if ( deblog || tn_deb || debses )
  1278.                 ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ",
  1279.                            TN_MSG_LEN);
  1280.             i++;
  1281.         }
  1282.     }
  1283.  
  1284.     return(i);
  1285. }
  1286. #endif /* CK_SRP */
  1287.  
  1288. #ifdef CK_SSL
  1289. static int
  1290. ck_tn_auth_request_ssl(int i)
  1291. {
  1292.     if (ck_ssleay_is_installed()
  1293.          && !tls_active_flag && !ssl_active_flag && ssl_initialized
  1294.          ) {
  1295.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1296.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1297.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1298.                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1299.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1300.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1301.         {
  1302.             str_request[i++] = AUTHTYPE_SSL;
  1303.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1304.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1305.             if ( deblog || tn_deb || debses )
  1306.                 ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ",
  1307.                            TN_MSG_LEN);
  1308.             i++;
  1309.         }
  1310.     }
  1311.  
  1312.     return(i);
  1313. }
  1314. #endif /* CK_SSL */
  1315. #ifdef NTLM
  1316. static int
  1317. ck_tn_auth_request_ntlm(int i)
  1318. {
  1319.     /* Microsoft's Telnet client won't perform authentication if */
  1320.     /* NTLM is not first.                                        */
  1321.     if ( ck_ntlm_is_valid(1) ) {
  1322.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1323.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1324.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1325.                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1326.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1327.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1328.         {
  1329.             str_request[i++] = AUTHTYPE_NTLM;
  1330.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1331.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1332.             if ( deblog || tn_deb || debses )
  1333.                 ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ",
  1334.                            TN_MSG_LEN);
  1335.             i++;
  1336.         }
  1337.     }
  1338.  
  1339.     return(i);
  1340. }
  1341. #endif /* NTLM */
  1342. int
  1343. #ifdef CK_ANSIC
  1344. ck_tn_auth_request(void)
  1345. #else
  1346. ck_tn_auth_request()
  1347. #endif
  1348. {
  1349.     int i = 4, rc = -1;
  1350.  
  1351. #ifdef CK_SSL
  1352.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1353.     return(0);
  1354.     }
  1355. #endif /* CK_SSL */
  1356.  
  1357.     if ( deblog || tn_deb || debses )
  1358.         strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
  1359.  
  1360.     /* Create a list of acceptable Authentication types to send to */
  1361.     /* the client and let it choose find one that we support       */
  1362.  
  1363.     /* For those authentication methods that support Encryption or */
  1364.     /* Credentials Forwarding we must send all of the appropriate  */
  1365.     /* combinations based upon the state of                        */
  1366.     /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag.          */
  1367.  
  1368.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  1369. #ifdef GSSAPI_K5
  1370.         i = ck_tn_auth_request_gsskrb5(i);
  1371. #endif /* GSSAPI_K5 */
  1372. #ifdef KRB5
  1373.         i = ck_tn_auth_request_krb5(i);
  1374. #endif /* KRB5 */
  1375. #ifdef KRB4
  1376.         i = ck_tn_auth_request_krb4(i);
  1377. #endif /* KRB4 */
  1378. #ifdef CK_SRP
  1379.         i = ck_tn_auth_request_srp(i);
  1380. #endif /* SRP */
  1381. #ifdef CK_SSL
  1382.         i = ck_tn_auth_request_ssl(i);
  1383. #endif /* CK_SSL */
  1384. #ifdef NTLM
  1385.         i = ck_tn_auth_request_ntlm(i);
  1386. #endif /* NTLM */
  1387.     } else {
  1388.         int j;
  1389.         for ( j=0;
  1390.               j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
  1391.               j++) {
  1392. #ifdef NTLM
  1393.             if (auth_type_user[j] == AUTHTYPE_NTLM)
  1394.                 i = ck_tn_auth_request_ntlm(i);
  1395. #endif /* NTLM */
  1396. #ifdef CK_SSL
  1397.             if ( auth_type_user[j] == AUTHTYPE_SSL )
  1398.                 i = ck_tn_auth_request_ssl(i);
  1399. #endif /* CK_SSL */
  1400. #ifdef CK_SRP
  1401.             if ( auth_type_user[j] == AUTHTYPE_SRP )
  1402.                 i = ck_tn_auth_request_srp(i);
  1403. #endif /* SRP */
  1404. #ifdef GSSAPI_K5
  1405.             if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 )
  1406.                 i = ck_tn_auth_request_gsskrb5(i);
  1407. #endif /* GSSAPI_K5 */
  1408. #ifdef KRB5
  1409.             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 )
  1410.                 i = ck_tn_auth_request_krb5(i);
  1411. #endif /* KRB5 */
  1412. #ifdef KRB4
  1413.             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 )
  1414.                 i = ck_tn_auth_request_krb4(i);
  1415. #endif /* KRB4 */
  1416.         }
  1417.     }
  1418.  
  1419.     str_request[i++] = IAC;
  1420.     str_request[i++] = SE;
  1421.     if ( deblog || tn_deb || debses ) {
  1422.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1423.     debug(F100,tn_msg,"",0);
  1424.     if (tn_deb || debses) tn_debug(tn_msg);
  1425.     }
  1426.  
  1427.     /* Send data */
  1428.     rc = ttol((CHAR *)str_request, i);
  1429.     if ( rc == i )
  1430.         return(0);
  1431.     else
  1432.         return(-1);
  1433. }
  1434.  
  1435. #ifdef CK_ENCRYPTION
  1436. VOID
  1437. ck_tn_enc_start()
  1438. {
  1439.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1440.         return;
  1441.     if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
  1442.      (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
  1443.     debug(F110,"ck_tn_enc_start","nothing to do",0);
  1444.         return;
  1445.     }
  1446.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1447.     if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
  1448.     debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
  1449.         encrypt_request_start();
  1450.     }
  1451.     if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
  1452.     debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
  1453.         encrypt_send_request_start();
  1454.     }
  1455.     tn_wait("encrypt start");
  1456.     tn_push();
  1457. }
  1458.  
  1459. VOID
  1460. ck_tn_enc_stop()
  1461. {
  1462.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1463.         return;
  1464.     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
  1465.      !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
  1466.     debug(F110,"ck_tn_enc_stop","nothing to do",0);
  1467.       return;
  1468.     }
  1469.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1470.     if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
  1471.     debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
  1472.         encrypt_send_request_end();
  1473.     }
  1474.     if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
  1475.     debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
  1476.         encrypt_send_end();
  1477.     }
  1478.     tn_wait("encrypt stop");
  1479.     tn_push();
  1480. }
  1481. #endif /* CK_ENCRYPTION */
  1482.  
  1483. /*  C K _ K R B _ T N _ S B _ A U T H
  1484.  *  An interface between the C-Kermit Telnet Command Parser and the Authent-
  1485.  *  ication option parser implemented in the Kerberos Telnet client.
  1486.  *
  1487.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1488.  *  len  - the length of the buffer
  1489.  *
  1490.  *  Returns: 0 on success and -1 on failure
  1491.  */
  1492.  
  1493. int
  1494. #ifdef CK_ANSIC
  1495. ck_tn_sb_auth(char * sb, int len)
  1496. #else /* CK_ANSIC */
  1497. ck_tn_sb_auth(sb,len) char * sb; int len;
  1498. #endif /* CK_ANSIC */
  1499. {
  1500.     /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1501.     /* and it wants the length to exclude the IAC SE bytes                  */
  1502.     char * buf;
  1503.     int rc = -1;
  1504.  
  1505.     buf = malloc(len-1);
  1506.     if ( !buf ) return(-1);
  1507.  
  1508.     buf[0] = SB;
  1509.     memcpy( &buf[1], sb, len-2 );
  1510.     rc = auth_parse(buf,len-1);
  1511.     free(buf);
  1512.     debug(F111,"ck_tn_sb_auth","rc",rc);
  1513.     if (rc == AUTH_FAILURE) {
  1514.         authentication_version = AUTHTYPE_NULL;
  1515. #ifndef NOLOCAL
  1516. #ifdef OS2
  1517.         ipadl25();
  1518. #endif /* OS2 */
  1519. #endif /* NOLOCAL */
  1520.         return(-1);
  1521.     }
  1522. #ifndef NOLOCAL
  1523. #ifdef OS2
  1524.     ipadl25();
  1525. #endif /* OS2 */
  1526. #endif /* NOLOCAL */
  1527.     return(0);
  1528. }
  1529.  
  1530. /*  C K _ K R B _ T N _ S B _ E N C R Y P T
  1531.  *  An interface between the C-Kermit Telnet Command Parser and the Encryption
  1532.  *  option parser implemented in the Kerberos Telnet client.
  1533.  *
  1534.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1535.  *  len  - the length of the buffer
  1536.  *
  1537.  *  Returns: Always returns 0 for success since encrypt_parse is void
  1538.  */
  1539.  
  1540.  
  1541. int
  1542. #ifdef CK_ANSIC
  1543. ck_tn_sb_encrypt(char * sb, int len)
  1544. #else
  1545. ck_tn_sb_encrypt(sb,len) char * sb; int len;
  1546. #endif /* CK_ANSIC */
  1547. {
  1548.     /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1549.     /* and it wants the length to exclude the IAC SE bytes                  */
  1550. #ifdef CK_ENCRYPTION
  1551.     char * buf;
  1552.     int rc = -1;
  1553.  
  1554.     buf = malloc(len-1);
  1555.     if ( !buf ) return(-1);
  1556.  
  1557.     buf[0] = SB;
  1558.     memcpy( &buf[1], sb, len-2 );
  1559.     rc = encrypt_parse(buf,len-1);
  1560.  
  1561.     if (rc < 0) {
  1562.         free(buf);
  1563.     return(-1);
  1564.     }
  1565.  
  1566.     /* This is a hack.  It does not belong here but should really be in */
  1567.     /* encrypt_parse() but in K95 the encrypt_parse() routine does not  */
  1568.     /* have access to the telopt_states array.                          */
  1569.     if ( buf[1] == ENCRYPT_REQEND )
  1570.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1571.     else if ( buf[1] == ENCRYPT_REQSTART )
  1572.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1573. #ifndef NOLOCAL
  1574. #ifdef OS2
  1575.     ipadl25();
  1576. #endif /* OS2 */
  1577. #endif /* NOLOCAL */
  1578.     free(buf);
  1579. #endif /* ENCRYPTION */
  1580.     return(0);
  1581. }
  1582.  
  1583.  
  1584. /*  C K _ K R B _ E N C R Y P T I N G
  1585.  *  Returns 1 if we are encrypting and 0 if we are not
  1586.  */
  1587.  
  1588. int
  1589. #ifdef CK_ANSIC
  1590. ck_tn_encrypting(VOID)
  1591. #else /* CK_ANSIC */
  1592. ck_tn_encrypting()
  1593. #endif /* CK_ANSIC */
  1594. {
  1595. #ifdef CK_ENCRYPTION
  1596.     if ( g_kstream == NULL )
  1597.         return(0);
  1598.     if ( g_kstream->encrypt && encrypt_is_encrypting()) {
  1599.     debug(F111,"ck_tn_encrypting","encrypting",
  1600.            g_kstream->encrypt_type);
  1601.         return(g_kstream->encrypt_type);
  1602.     }
  1603. #endif /* CK_ENCRYPTION */
  1604.     debug(F110,"ck_tn_encrypting","not encrypting",0);
  1605.     return(0);
  1606. }
  1607.  
  1608. /*  C K _ K R B _ D E C R Y P T I N G
  1609.  *  Returns 1 if we are decrypting and 0 if we are not
  1610.  */
  1611.  
  1612. int
  1613. #ifdef CK_ANSIC
  1614. ck_tn_decrypting(VOID)
  1615. #else
  1616. ck_tn_decrypting()
  1617. #endif /* CK_ANSIC */
  1618. {
  1619. #ifdef CK_ENCRYPTION
  1620.     if ( g_kstream == NULL )
  1621.         return(0);
  1622.     if ( g_kstream->decrypt && encrypt_is_decrypting()) {
  1623.     debug(F111,"ck_tn_decrypting","decrypting",
  1624.            g_kstream->decrypt_type);
  1625.         return(g_kstream->decrypt_type);
  1626.     }
  1627. #endif /* CK_ENCRYPTION */
  1628.     debug(F110,"ck_tn_decrypting","not decrypting",0);
  1629.     return(0);
  1630. }
  1631.  
  1632. /*  C K _ K R B _ A U T H E N T I C A T E D
  1633.  *  Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
  1634.  *  or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
  1635.  */
  1636.  
  1637. int
  1638. #ifdef CK_ANSIC
  1639. ck_tn_authenticated(VOID)
  1640. #else
  1641. ck_tn_authenticated()
  1642. #endif
  1643. {
  1644.     return(authentication_version);
  1645. }
  1646.  
  1647. /*  C K _ K R B _ E N C R Y P T
  1648.  *  encrypts n characters in s if we are encrypting
  1649.  */
  1650.  
  1651. VOID
  1652. #ifdef CK_ANSIC
  1653. ck_tn_encrypt( char * s, int n )
  1654. #else
  1655. ck_tn_encrypt( s,n ) char * s; int n;
  1656. #endif
  1657. {
  1658. #ifdef CK_ENCRYPTION
  1659.     struct kstream_data_block i;
  1660.  
  1661.     if (g_kstream->encrypt && encrypt_is_encrypting()) {
  1662. #ifdef DEBUG
  1663.       hexdump("from plaintext", s, n);
  1664. #endif
  1665.         i.ptr = s;
  1666.         i.length = n;
  1667.         g_kstream->encrypt(&i, NULL);
  1668. #ifdef DEBUG
  1669.         hexdump("to cyphertext", s, n);
  1670. #endif
  1671.     }
  1672.     else debug(F101,"ck_tn_encrypt not encrypting","",n);
  1673. #endif /* ENCRYPTION */
  1674. }
  1675.  
  1676. /*  C K _ K R B _ D E C R Y P T
  1677.  *  decrypts n characters in s if we are decrypting
  1678.  */
  1679.  
  1680. VOID
  1681. #ifdef CK_ANSIC
  1682. ck_tn_decrypt( char * s, int n )
  1683. #else
  1684. ck_tn_decrypt( s,n ) char * s; int n;
  1685. #endif
  1686. {
  1687. #ifdef CK_ENCRYPTION
  1688.     struct kstream_data_block i;
  1689.  
  1690.     if (g_kstream->decrypt && encrypt_is_decrypting()) {
  1691.  
  1692. #ifdef DEBUG
  1693.         hexdump("from cyphertext", s, n);
  1694. #endif
  1695.  
  1696.         i.ptr = s;
  1697.         i.length = n;
  1698.         g_kstream->decrypt(&i, NULL);
  1699. #ifdef DEBUG
  1700.         hexdump("to plaintext", s, n);
  1701. #endif
  1702.     }
  1703.     else debug(F101,"ck_tn_decrypt not decrypting","",n);
  1704. #endif /* ENCRYPTION */
  1705. }
  1706.  
  1707. /*  S E N D K 5 A U T H S B
  1708.  *  Send a Kerberos 5 Authentication Subnegotiation to host and
  1709.  *  output appropriate Telnet Debug messages
  1710.  *
  1711.  *  type - Sub Negotiation type
  1712.  *  data - ptr to buffer containing data
  1713.  *  len  - len of buffer if not NUL terminated
  1714.  *
  1715.  *  returns number of characters sent or error value
  1716.  */
  1717.  
  1718. static int
  1719. #ifdef CK_ANSIC
  1720. SendK5AuthSB(int type, void *data, int len)
  1721. #else
  1722. SendK5AuthSB(type,data,len) int type; void *data; int len;
  1723. #endif
  1724. {
  1725.     int rc;
  1726.     unsigned char *p = str_data + 3;
  1727.     unsigned char *cd = (unsigned char *)data;
  1728.     extern int sstelnet;
  1729.  
  1730. #ifdef CK_SSL
  1731.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1732.         if (ttchk() < 0)
  1733.       return(0);
  1734.         else
  1735.       return(1);
  1736.     }
  1737. #endif /* CK_SSL */
  1738.  
  1739.     if ( type < 0 || type > 7 )         /* Check for invalid values */
  1740.         return(0);
  1741.  
  1742.     if (!cd) {
  1743.         cd = (unsigned char *)"";
  1744.         len = 0;
  1745.     }
  1746.  
  1747.     if (len == -1)                        /* Use strlen() for len */
  1748.         len = strlen((char *)cd);
  1749.  
  1750.     /* Construct Message */
  1751.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1752.     *p++ = AUTHTYPE_KERBEROS_V5;
  1753.     *p = AUTH_CLIENT_TO_SERVER;
  1754.     *p |= auth_how;
  1755. #ifdef CK_ENCRYPTION
  1756.     *p |= auth_crypt;
  1757. #endif
  1758. #ifdef USE_INI_CRED_FWD
  1759.     if (auth_fwd)
  1760.         *p |= INI_CRED_FWD_ON;
  1761. #endif /* USE_INI_CRED_FWD */
  1762.     p++;
  1763.     *p++ = type;
  1764.     while (len-- > 0) {
  1765.         if ((*p++ = *cd++) == IAC)
  1766.             *p++ = IAC;
  1767.     }
  1768.     *p++ = IAC;
  1769.     *p++ = SE;
  1770.  
  1771.     /* Handle Telnet Debugging Messages */
  1772.     if (deblog || tn_deb || debses) {
  1773.         int i;
  1774.         int deblen=p-str_data-2;
  1775.         char *s=NULL;
  1776.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1777.             auth_crypt
  1778. #ifdef USE_INI_CRED_FWD
  1779.               | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  1780. #endif /* USE_INI_CRED_FWD */
  1781.                     ;
  1782.  
  1783.         switch (type) {
  1784.         case 0:
  1785.             s = "AUTH";
  1786.             break;
  1787.         case 1:
  1788.             s = "REJECT";
  1789.             break;
  1790.         case 2:
  1791.             s = "ACCEPT";
  1792.             break;
  1793.         case 3:
  1794.             s = "RESPONSE";
  1795.             break;
  1796.         case 4:
  1797.             s = "FORWARD";
  1798.             break;
  1799.         case 5:
  1800.             s = "FORWARD_ACCEPT";
  1801.             break;
  1802.         case 6:
  1803.             s = "FORWARD_REJECT";
  1804.             break;
  1805.         case 7:
  1806.             s = "TLS_VERIFY";
  1807.                 break;
  1808.         }
  1809.  
  1810.     ckmakxmsg(tn_msg,TN_MSG_LEN,
  1811.                   "TELNET SENT SB ",
  1812.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1813.                  str_data[3] == TELQUAL_IS ? "IS" :
  1814.                  str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ",
  1815.                  AUTHTYPE_NAME(authentication_version)," ",
  1816.                  AUTHMODE_NAME(mode)," ",
  1817.                  s," ",NULL);
  1818.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1819.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1820.     debug(F100,tn_msg,"",0);
  1821.     if (tn_deb || debses) tn_debug(tn_msg);
  1822.     }
  1823.  
  1824.     /* Send data */
  1825.     rc = ttol((CHAR *)str_data, p - str_data);
  1826.     debug(F111,"SendK5AuthSB","ttol()",rc);
  1827.     return(rc);
  1828. }
  1829.  
  1830. /*  S E N D K 4 A U T H S B
  1831.  *  Send a Kerberos 4 Authentication Subnegotiation to host and
  1832.  *  output appropriate Telnet Debug messages
  1833.  *
  1834.  *  type - Sub Negotiation type
  1835.  *  data - ptr to buffer containing data
  1836.  *  len  - len of buffer if not NUL terminated
  1837.  *
  1838.  *  returns number of characters sent or error value
  1839.  */
  1840.  
  1841. static int
  1842. #ifdef CK_ANSIC
  1843. SendK4AuthSB(int type, void *data, int len)
  1844. #else
  1845. SendK4AuthSB(type,data,len) int type; void *data; int len;
  1846. #endif
  1847. {
  1848.     int rc;
  1849.     unsigned char *p = str_data + 3;
  1850.     unsigned char *cd = (unsigned char *)data;
  1851.     extern int sstelnet;
  1852.     int mode = (auth_how & AUTH_HOW_MASK) |
  1853.         auth_crypt;
  1854.  
  1855.     if ( type < 0 || type > 4 )         /* Check for invalid values */
  1856.         return(0);
  1857.  
  1858. #ifdef CK_SSL
  1859.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1860.         if (ttchk() < 0)
  1861.       return(0);
  1862.         else
  1863.       return(1);
  1864.     }
  1865. #endif /* CK_SSL */
  1866.  
  1867.     if (!cd) {
  1868.         cd = (unsigned char *)"";
  1869.         len = 0;
  1870.     }
  1871.  
  1872.     if (len == -1)                        /* Use strlen() for len */
  1873.         len = strlen((char *)cd);
  1874.  
  1875.  
  1876.     /* Construct Message */
  1877.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1878.     *p++ = AUTHTYPE_KERBEROS_V4;
  1879.     *p = AUTH_CLIENT_TO_SERVER;
  1880.     *p |= mode;
  1881.     p++;
  1882.     *p++ = type;
  1883.     while (len-- > 0) {
  1884.         if ((*p++ = *cd++) == IAC)
  1885.             *p++ = IAC;
  1886.         }
  1887.     *p++ = IAC;
  1888.     *p++ = SE;
  1889.  
  1890.     /* Handle Telnet Debugging Messages */
  1891.     if (deblog || tn_deb || debses) {
  1892.         int i;
  1893.         int deblen=p-str_data-2;
  1894.         char *s=NULL;
  1895.  
  1896.         switch (type) {
  1897.         case 0:
  1898.             s = "AUTH";
  1899.             break;
  1900.         case 1:
  1901.             s = "REJECT";
  1902.             break;
  1903.         case 2:
  1904.             s = "ACCEPT";
  1905.             break;
  1906.         case 3:
  1907.             s = "CHALLENGE";
  1908.             break;
  1909.         case 4:
  1910.             s = "RESPONSE";
  1911.             break;
  1912.         }
  1913.  
  1914.     ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ",
  1915.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1916.                  str_data[3] == TELQUAL_IS ? "IS" :
  1917.                  (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ",
  1918.                  AUTHTYPE_NAME(authentication_version)," ",
  1919.                  AUTHMODE_NAME(mode)," ",
  1920.                  s," ",NULL);
  1921.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1922.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1923.     debug(F100,tn_msg,"",0);
  1924.     if (tn_deb || debses) tn_debug(tn_msg);
  1925.     }
  1926.  
  1927.     /* Send data */
  1928.     rc = ttol((CHAR *)str_data, p - str_data);
  1929.     debug(F111,"SendK4AuthSB","ttol()",rc);
  1930.     return(rc);
  1931. }
  1932.  
  1933. /*  S E N D S R P A U T H S B
  1934.  *  Send a SRP Authentication Subnegotiation to host and
  1935.  *  output appropriate Telnet Debug messages
  1936.  *
  1937.  *  type - Sub Negotiation type
  1938.  *  data - ptr to buffer containing data
  1939.  *  len  - len of buffer if not NUL terminated
  1940.  *
  1941.  *  returns number of characters sent or error value
  1942.  */
  1943.  
  1944. static int
  1945. #ifdef CK_ANSIC
  1946. SendSRPAuthSB(int type, void *data, int len)
  1947. #else
  1948. SendSRPAuthSB(type,data,len) int type; void *data; int len;
  1949. #endif
  1950. {
  1951.     int rc;
  1952.     unsigned char *p = str_data + 3;
  1953.     unsigned char *cd = (unsigned char *)data;
  1954.     extern int sstelnet;
  1955.  
  1956.     /* Check for invalid values */
  1957.     if ( type != SRP_EXP && type != SRP_RESPONSE &&
  1958.          type != SRP_REJECT && type != SRP_ACCEPT &&
  1959.          type != SRP_CHALLENGE && type != SRP_PARAMS &&
  1960.          type != SRP_AUTH)
  1961.         return(0);
  1962.  
  1963.     if (len == -1)                        /* Use strlen() for len */
  1964.         len = strlen((char *)cd);
  1965.  
  1966.     /* Construct Message */
  1967.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1968.     *p++ = AUTHTYPE_SRP;
  1969.     *p = AUTH_CLIENT_TO_SERVER;
  1970.     *p |= auth_how;
  1971. #ifdef CK_ENCRYPTION
  1972.     *p |= auth_crypt;
  1973. #endif
  1974.     p++;
  1975.     *p++ = type;
  1976.     while (len-- > 0) {
  1977.         if ((*p++ = *cd++) == IAC)
  1978.             *p++ = IAC;
  1979.         }
  1980.     *p++ = IAC;
  1981.     *p++ = SE;
  1982.  
  1983.     /* Handle Telnet Debugging Messages */
  1984.     if (deblog || tn_deb || debses) {
  1985.         int i;
  1986.         int deblen=p-str_data-2;
  1987.         char *s=NULL;
  1988.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1989.             auth_crypt;
  1990.  
  1991.         switch (type) {
  1992.         case 0:
  1993.             s = "AUTH";
  1994.             break;
  1995.         case 1:
  1996.             s = "REJECT";
  1997.             break;
  1998.         case 2:
  1999.             s = "ACCEPT";
  2000.             break;
  2001.         case 3:
  2002.             s = "CHALLENGE";
  2003.             break;
  2004.         case 4:
  2005.             s = "RESPONSE";
  2006.             break;
  2007.         case 5:
  2008.             s = "FORWARD";
  2009.             break;
  2010.         case 6:
  2011.             s = "FORWARD_ACCEPT";
  2012.             break;
  2013.         case 7:
  2014.             s = "FORWARD_REJECT";
  2015.             break;
  2016.         case 8:
  2017.             s = "EXP";
  2018.             break;
  2019.         case 9:
  2020.             s = "PARAMS";
  2021.             break;
  2022.         }
  2023.  
  2024.     ckmakxmsg(tn_msg,TN_MSG_LEN,
  2025.                   "TELNET SENT SB ",
  2026.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  2027.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  2028.                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
  2029.                  AUTHTYPE_NAME(authentication_version)," ",
  2030.                  AUTHMODE_NAME(mode)," ",
  2031.                  s," ",NULL);
  2032.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  2033.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  2034.     debug(F100,tn_msg,"",0);
  2035.     if (tn_deb || debses) tn_debug(tn_msg);
  2036.     }
  2037.  
  2038.     /* Send data */
  2039.     rc = ttol((CHAR *)str_data, p - str_data);
  2040.     return(rc);
  2041. }
  2042.  
  2043. #ifdef CK_ENCRYPTION
  2044. /*
  2045.  * Function: Enable or disable the encryption process.
  2046.  *
  2047.  * Parameters:
  2048.  *    enable - TRUE to enable, FALSE to disable.
  2049.  */
  2050. static VOID
  2051. #ifdef CK_ANSIC
  2052. auth_encrypt_enable(BOOL enable)
  2053. #else
  2054. auth_encrypt_enable(enable) BOOL enable;
  2055. #endif
  2056. {
  2057.   encrypt_flag = enable;
  2058. }
  2059. #endif
  2060.  
  2061. /*
  2062.  * Function: Abort the authentication process
  2063.  *
  2064.  * Parameters:
  2065.  */
  2066. static VOID
  2067. #ifdef CK_ANSIC
  2068. auth_abort(char *errmsg, long r)
  2069. #else
  2070. auth_abort(errmsg,r) char *errmsg; long r;
  2071. #endif
  2072. {
  2073.     char buf[9];
  2074.     extern int sstelnet;
  2075.  
  2076. #ifdef CK_SSL
  2077.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  2078.     return;
  2079.     }
  2080. #endif /* CK_SSL */
  2081.     debug(F111,"auth_abort",errmsg,r);
  2082.  
  2083.     /* Construct Telnet Debugging messages */
  2084.     if (deblog || tn_deb || debses) {
  2085.     ckmakxmsg(tn_msg,TN_MSG_LEN,
  2086.                   "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2087.                   " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ",
  2088.                    AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE",
  2089.                    NULL,NULL,NULL,NULL,NULL
  2090.                  );
  2091.     debug(F100,tn_msg,"",0);
  2092.     if (tn_deb || debses) tn_debug(tn_msg);
  2093.     }
  2094.  
  2095.     /* Construct the Abort message to send to the host   */
  2096.     /* Basicly we change the authentication type to NULL */
  2097.     sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  2098.              sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
  2099.              AUTHTYPE_NULL, IAC, SE);   /* safe */
  2100.     ttol((CHAR *)buf, 8);
  2101.  
  2102.     /* If there is an error message, and error number construct */
  2103.     /* an explanation to display to the user                    */
  2104.     if (errmsg != NULL) {
  2105.         ckstrncpy(strTmp, errmsg, AUTHTMPBL);
  2106.     } else
  2107.         strTmp[0] = '\0';
  2108.  
  2109.  
  2110.     if (r != AUTH_SUCCESS) {
  2111.         ckstrncat(strTmp, "\r\n",AUTHTMPBL);
  2112. #ifdef KRB4
  2113.         if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
  2114.             ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),
  2115.                AUTHTMPBL);
  2116.             debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
  2117.         }
  2118. #endif
  2119. #ifdef KRB5
  2120.         if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
  2121.             ckstrncat(strTmp, error_message(r),AUTHTMPBL);
  2122.             debug(F111,"auth_abort",error_message(r),r);
  2123.         }
  2124. #endif
  2125.     }
  2126.     printf("Authentication failed: %s\r\n",strTmp);
  2127. #ifdef CKSYSLOG
  2128.     if (ckxsyslog >= SYSLG_LI && ckxlogging) {
  2129.         cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
  2130.                   (char *) szUserNameRequested,
  2131.                   strTmp);
  2132.     }
  2133. #endif /* CKSYSLOG */
  2134.     authentication_version = AUTHTYPE_NULL;
  2135. }
  2136.  
  2137.  
  2138. /*
  2139.  * Function: Copy data to buffer, doubling IAC character if present.
  2140.  *
  2141.  */
  2142. int
  2143. #ifdef CK_ANSIC
  2144. copy_for_net(unsigned char *to, unsigned char *from, int c)
  2145. #else
  2146. copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
  2147. #endif
  2148. {
  2149.     int n;
  2150.  
  2151.     n = c;
  2152.     debug(F111,"copy_for_net","before",n);
  2153.     while (c-- > 0) {
  2154.         if ((*to++ = *from++) == IAC) {
  2155.             n++;
  2156.             *to++ = IAC;
  2157.         }
  2158.     }
  2159.     debug(F111,"copy_for_net","after",n);
  2160.     return n;
  2161. }
  2162.  
  2163. #ifdef CK_SSL
  2164. /*  S E N D S S L A U T H S B
  2165.  *  Send a SSL Authentication Subnegotiation to host and
  2166.  *  output appropriate Telnet Debug messages
  2167.  *
  2168.  *  type - Sub Negotiation type
  2169.  *  data - ptr to buffer containing data
  2170.  *  len  - len of buffer if not NUL terminated
  2171.  *
  2172.  *  returns number of characters sent or error value
  2173.  */
  2174.  
  2175. int
  2176. #ifdef CK_ANSIC
  2177. SendSSLAuthSB(int type, void *data, int len)
  2178. #else
  2179. SendSSLAuthSB(type,data,len) int type; void *data; int len;
  2180. #endif
  2181. {
  2182.     int rc;
  2183.     unsigned char *p = str_data + 3;
  2184.     unsigned char *cd = (unsigned char *)data;
  2185.     extern int sstelnet;
  2186.  
  2187.     /* Check for invalid values */
  2188.     if ( type != SSL_START && type != SSL_ACCEPT &&
  2189.          type != SSL_REJECT)
  2190.         return(0);
  2191.  
  2192.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  2193.         if (ttchk() < 0)
  2194.       return(0);
  2195.         else
  2196.       return(1);
  2197.     }
  2198.  
  2199.     if (len == -1)                        /* Use strlen() for len */
  2200.         len = strlen((char *)cd);
  2201.  
  2202.     /* Construct Message */
  2203.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  2204.     *p++ = AUTHTYPE_SSL;
  2205.     *p = AUTH_CLIENT_TO_SERVER;
  2206.     *p |= auth_how;
  2207. #ifdef CK_ENCRYPTION
  2208.     *p |= auth_crypt;
  2209. #endif
  2210.     p++;
  2211.     *p++ = type;
  2212.     while (len-- > 0) {
  2213.         if ((*p++ = *cd++) == IAC)
  2214.             *p++ = IAC;
  2215.         }
  2216.     *p++ = IAC;
  2217.     *p++ = SE;
  2218.  
  2219.     /* Handle Telnet Debugging Messages */
  2220.     if (deblog || tn_deb || debses) {
  2221.         int i;
  2222.         int deblen=p-str_data-2;
  2223.         char *s=NULL;
  2224.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  2225.             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
  2226.  
  2227.         switch (type) {
  2228.         case SSL_START:
  2229.             s = "START";
  2230.             break;
  2231.         case SSL_ACCEPT:
  2232.             s = "ACCEPT";
  2233.             break;
  2234.         case SSL_REJECT:
  2235.             s = "REJECT";
  2236.             break;
  2237.         }
  2238.  
  2239.     ckmakxmsg(tn_msg,TN_MSG_LEN,
  2240.                   "TELNET SENT SB ",
  2241.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  2242.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  2243.                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
  2244.                  AUTHTYPE_NAME(authentication_version)," ",
  2245.                  AUTHMODE_NAME(mode)," ",
  2246.                  s," ",NULL);
  2247.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  2248.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  2249.     debug(F100,tn_msg,"",0);
  2250.     if (tn_deb || debses) tn_debug(tn_msg);
  2251.     }
  2252.  
  2253.     /* Send data */
  2254.     rc = ttol((CHAR *)str_data, p - str_data);
  2255.     return(rc);
  2256. }
  2257. #endif  /* CK_SSL */
  2258.  
  2259. int
  2260. tn_how_ok(int how)
  2261. {
  2262.     switch ( tn_auth_how ) {
  2263.     case TN_AUTH_HOW_ANY:
  2264.         return(1);
  2265.     case TN_AUTH_HOW_ONE_WAY:
  2266.         return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
  2267.     case TN_AUTH_HOW_MUTUAL:
  2268.         return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
  2269.     default:
  2270.         return(0);
  2271.     }
  2272. }
  2273.  
  2274. int
  2275. tn_enc_ok(int enc)
  2276. {
  2277.     switch ( tn_auth_enc ) {
  2278.     case TN_AUTH_ENC_ANY:
  2279.         if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
  2280.             (!ck_ssleay_is_installed
  2281. #ifdef CK_SSL
  2282.              || !ssl_finished_messages ||
  2283.              !(tls_active_flag || ssl_active_flag)
  2284. #endif /* CK_SSL */
  2285.              )) {
  2286. #ifdef CK_SSL
  2287.             if (!ssl_finished_messages)
  2288.                 debug(F100,"tn_enc_ok !ssl_finished_messages","",0);
  2289. #endif /* CK_SSL */
  2290.             return(0);
  2291.         }
  2292.         return(1);
  2293.     case TN_AUTH_ENC_NONE:
  2294.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
  2295.     case TN_AUTH_ENC_TELOPT:
  2296.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
  2297.     case TN_AUTH_ENC_EXCH:
  2298.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
  2299.     case TN_AUTH_ENC_TLS:
  2300.         return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) &&
  2301.                ck_ssleay_is_installed()
  2302. #ifdef CK_SSL
  2303.                && ssl_finished_messages &&
  2304.                (tls_active_flag || ssl_active_flag)
  2305. #endif /* CK_SSL */
  2306.            );
  2307.     default:
  2308.         return(0);
  2309.     }
  2310. }
  2311.  
  2312. static int
  2313. atok(int at) {
  2314.     int i;
  2315.     if ( auth_type_user[0] == AUTHTYPE_AUTO )
  2316.         return(1);
  2317.     if ( auth_type_user[0] == AUTHTYPE_NULL )
  2318.         return(0);
  2319.  
  2320.     for ( i=0;
  2321.           i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
  2322.           i++ ) {
  2323.         if ( auth_type_user[i] == at )
  2324.             return(1);
  2325.     }
  2326.  
  2327.     return(0);
  2328. }
  2329.  
  2330.  
  2331. /*
  2332.  * Function: Parse authentication send command
  2333.  *
  2334.  * Parameters:
  2335.  *  parsedat - the sub-command data.
  2336.  *
  2337.  *    end_sub - index of the character in the 'parsedat' array which
  2338.  *        is the last byte in a sub-negotiation
  2339.  *
  2340.  * Returns: Kerberos error code.
  2341.  */
  2342.  
  2343. static unsigned char send_list[512];
  2344. static int  send_len = 0;
  2345.  
  2346. _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub));
  2347.  
  2348. static int
  2349. #ifdef CK_ANSIC
  2350. auth_resend(int type)
  2351. #else
  2352. auth_resend(type) int type;
  2353. #endif /* CK_ANSIC */
  2354. {
  2355.     int i=2;
  2356.     while (i+1 <= send_len) {
  2357.         if (send_list[i] == type) {
  2358.             int j;
  2359.             send_len -= 2;
  2360.             for (j = i; j < send_len; j++)
  2361.                 send_list[j] = send_list[j+2];
  2362.         } else {
  2363.             i += 2;
  2364.         }
  2365.     }
  2366.     return(auth_send(send_list,send_len));
  2367. }
  2368.  
  2369. static int
  2370. #ifdef CK_ANSIC
  2371. auth_send(unsigned char *parsedat, int end_sub)
  2372. #else
  2373. auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  2374. #endif
  2375. {
  2376.     static unsigned char buf[4096];
  2377.     unsigned char *pname;
  2378.     int plen;
  2379.     int r;
  2380.     int i;
  2381.     int mode;
  2382. #ifdef MIT_CURRENT
  2383. #ifdef CK_ENCRYPTION
  2384.     krb5_data data;
  2385.     krb5_enc_data encdata;
  2386.     krb5_error_code code;
  2387.     krb5_keyblock random_key;
  2388. #endif /* ENCRYPTION */
  2389. #endif /* MIT_CURRENT */
  2390. #ifdef KRB5
  2391.     int krb5_msg = 0;
  2392. #endif /* KRB5 */
  2393. #ifdef KRB4
  2394.     int krb4_msg = 0;
  2395. #endif /* KRB4 */
  2396. #ifdef GSSAPI_KRB5
  2397.     int gssk5_msg = 0;
  2398. #endif /* GSSAPI_KRB5 */
  2399.     int iaccnt=0;
  2400.  
  2401. #ifdef CK_SSL
  2402.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  2403.     return(AUTH_SUCCESS);
  2404. #endif /* CK_SSL */
  2405.  
  2406.     auth_how = -1;              /* We have not found an auth method  */
  2407.     auth_crypt = 0;             /* We are not using encryption (yet) */
  2408.     send_len = end_sub > 512 ? 512 : end_sub;
  2409.     memcpy(send_list,parsedat,send_len);
  2410.  
  2411.     /* Search the list of acceptable Authentication types sent from */
  2412.     /* the host and find one that we support                        */
  2413.  
  2414.     /* For Kerberos authentications, try to determine if we have a  */
  2415.     /* valid TGT, if not skip over the authentication type because  */
  2416.     /* we wouldn't be able to successfully login anyway.  Perhaps   */
  2417.     /* there is another supported authentication which we could use */
  2418.  
  2419. #ifdef NO_FTP_AUTH
  2420.     /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
  2421.     /* for Kerberos or SRP.                                         */
  2422. #endif /* NO_FTP_AUTH */
  2423.  
  2424.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  2425.     for (i = 2; i+1 <= end_sub; i += 2) {
  2426. #ifdef NTLM
  2427.         if (parsedat[i] == AUTHTYPE_NTLM &&
  2428.              ck_ntlm_is_valid(1) &&
  2429.              ntlm_auth_send() == 0) {
  2430.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2431.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2432. #ifdef CK_ENCRYPTION
  2433.                 /* NTLM does not support Telnet Encryption */
  2434.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2435.                     continue;
  2436.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2437. #endif /* CK_ENCRYPTION */
  2438.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2439.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2440.                 authentication_version = AUTHTYPE_NTLM;
  2441.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2442.                 break;
  2443.             }
  2444.         }
  2445. #endif /* NTLM */
  2446. #ifdef CK_SSL
  2447.         if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
  2448. #ifdef SSLDLL
  2449.              ck_ssleay_is_installed() &&
  2450. #endif /* SSLDLL */
  2451.              !tls_active_flag && !ssl_active_flag
  2452. #ifndef USE_CERT_CB
  2453.              && tls_load_certs(ssl_ctx,ssl_con,0)
  2454. #endif /* USE_CERT_CB */
  2455.              ) {
  2456.  
  2457.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2458.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2459. #ifdef CK_ENCRYPTION
  2460.                 /* SSL does not support Telnet Encryption */
  2461.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2462.                     continue;
  2463.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2464. #endif /* CK_ENCRYPTION */
  2465.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2466.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2467.                 authentication_version = AUTHTYPE_SSL;
  2468.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2469.                 break;
  2470.             }
  2471.         }
  2472. #endif /* SSL */
  2473. #ifdef CK_SRP
  2474.         if ( parsedat[i] == AUTHTYPE_SRP
  2475. #ifdef SRPDLL
  2476.              && hSRP
  2477. #endif /* SRPDLL */
  2478. #ifdef NO_FTP_AUTH
  2479.              && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2480. #endif /* NO_FTP_AUTH */
  2481.              ) {
  2482.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2483.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2484. #ifdef PRE_SRP_1_4_5
  2485.                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2486.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2487.                     continue;
  2488. #endif /* PRE_SRP_1_4_5 */
  2489.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2490.              AUTH_ENCRYPT_USING_TELOPT) &&
  2491.             (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2492.              TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2493.                     continue;
  2494.  
  2495.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2496. #ifdef CK_ENCRYPTION
  2497.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2498.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2499.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2500.                 }
  2501. #endif /* CK_ENCRYPTION */
  2502. #ifdef CK_SSL
  2503.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2504.                      ck_ssleay_is_installed() &&
  2505.                      (tls_active_flag || ssl_active_flag) ) {
  2506.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2507.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2508.                 }
  2509. #endif /* CK_SSL */
  2510.                 authentication_version = AUTHTYPE_SRP;
  2511.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2512.                 break;
  2513.             }
  2514.         }
  2515. #endif /* SRP */
  2516. #ifdef GSSAPI_KRB5
  2517.         if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
  2518.             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2519.         AUTH_ENCRYPT_AFTER_EXCHANGE &&
  2520. #ifdef OS2
  2521.             hGSSAPI &&
  2522. #endif /* OS2 */
  2523. #ifdef NO_FTP_AUTH
  2524.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2525. #endif /* NO_FTP_AUTH */
  2526.              ck_gssapi_is_installed() && !gssk5_msg)
  2527.         {
  2528.             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2529.                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2530.                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
  2531.             {
  2532.                 /* If we are auto-getting TGTs, try */
  2533.                 if ( !ck_krb5_is_tgt_valid() ) {
  2534.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2535.                 }
  2536.                 gssk5_msg = 1;
  2537.             }
  2538.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2539.                       AUTH_CLIENT_TO_SERVER &&
  2540.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2541.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2542. #ifdef CK_ENCRYPTION
  2543.                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
  2544.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2545.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2546.                 }
  2547. #endif /* CK_ENCRYPTION */
  2548.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2549.                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
  2550.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2551.                 break;
  2552.             }
  2553.         }
  2554. #endif /* GSSAPI_KRB5 */
  2555. #ifdef KRB5
  2556.         if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2557. #ifdef OS2
  2558.              hKRB5_32 &&
  2559. #endif /* OS2 */
  2560. #ifdef NO_FTP_AUTH
  2561.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2562. #endif /* NO_FTP_AUTH */
  2563.              ck_krb5_is_installed() && !krb5_msg) {
  2564.  
  2565.             /* Without encryption we can't perform mutual authentication */
  2566.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2567.                  !ck_crypt_is_installed())
  2568.                 continue;
  2569.  
  2570.             /* Skip over entries that request credential forwarding */
  2571.             /* if we are not forwarding.                            */
  2572.             if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2573.                 (forward_flag &&
  2574.                   ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2575.                 continue;
  2576.  
  2577.             if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2578.                                 parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2579.                                 parsedat[i+1] & INI_CRED_FWD_MASK) )
  2580.             {
  2581.                 /* If we are auto-getting TGTs, try */
  2582.                 if ( !ck_krb5_is_tgt_valid() ) {
  2583.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2584.                 }
  2585.                 krb5_msg = 1;
  2586.             }
  2587.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2588.                       AUTH_CLIENT_TO_SERVER &&
  2589.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2590.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2591.              AUTH_ENCRYPT_USING_TELOPT) &&
  2592.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2593.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2594.                     continue;
  2595.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2596.              AUTH_ENCRYPT_START_TLS) &&
  2597.                      (!ck_ssleay_is_installed()
  2598. #ifdef CK_SSL
  2599.                        || !(tls_active_flag || ssl_active_flag)
  2600. #endif /* CK_SSL */
  2601.                        ))
  2602.                     continue;
  2603.  
  2604.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2605. #ifdef CK_ENCRYPTION
  2606.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2607.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2608.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2609.                 }
  2610. #endif /* CK_ENCRYPTION */
  2611. #ifdef CK_SSL
  2612.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2613.                      ck_ssleay_is_installed() &&
  2614.                      (tls_active_flag || ssl_active_flag) ) {
  2615.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2616.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2617.                 }
  2618. #endif /* CK_SSL */
  2619.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2620.                 authentication_version = AUTHTYPE_KERBEROS_V5;
  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 /* KRB5 */
  2630. #ifdef KRB4
  2631.         if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2632. #ifdef OS2
  2633.              hKRB4_32 &&
  2634. #endif /* OS2 */
  2635. #ifdef NO_FTP_AUTH
  2636.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2637. #endif /* NO_FTP_AUTH */
  2638.              ck_krb4_is_installed() && !krb4_msg) {
  2639.             int rc = 0;
  2640.  
  2641.             /* Without encryption we can't perform mutual authentication */
  2642.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2643.                  !ck_crypt_is_installed() )
  2644.                 continue;
  2645.  
  2646.             if ( !k4_auth_send() )
  2647.             {
  2648.                 /* If we are auto-getting TGTs, try */
  2649.                 if ( !ck_krb4_is_tgt_valid() ) {
  2650.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2651.                 }
  2652.                 krb4_msg = 1;
  2653.             }
  2654.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2655.                       AUTH_CLIENT_TO_SERVER &&
  2656.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2657. #ifdef CK_ENCRYPTION
  2658.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2659.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2660.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2661.                     continue;
  2662.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2663.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2664.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2665.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2666.         }
  2667. #endif /* CK_ENCRYPTION */
  2668.                 authentication_version = AUTHTYPE_KERBEROS_V4;
  2669.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2670.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2671.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2672.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2673.                 }
  2674.                 break;
  2675.             }
  2676.         }
  2677. #endif /* KRB4 */
  2678.     }
  2679.     } else {
  2680.         for (i = 2; i+1 <= end_sub; i += 2) {
  2681. #ifdef CK_SSL
  2682.             if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
  2683. #ifdef SSLDLL
  2684.                  ck_ssleay_is_installed() &&
  2685. #endif /* SSLDLL */
  2686.                  !tls_active_flag && !ssl_active_flag && ssl_initialized
  2687. #ifndef USE_CERT_CB
  2688.                  && tls_load_certs(ssl_ctx,ssl_con,0)
  2689. #endif /* USE_CERT_CB */
  2690.                  )
  2691.             {
  2692.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2693.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2694. #ifdef CK_ENCRYPTION
  2695.                     /* SSL does not support Telnet Encryption */
  2696.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2697.                         continue;
  2698.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2699. #endif /* CK_ENCRYPTION */
  2700.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2701.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2702.                     authentication_version = AUTHTYPE_SSL;
  2703.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2704.                     break;
  2705.                 }
  2706.             }
  2707. #endif /* SSL */
  2708. #ifdef CK_SRP
  2709.             if ( atok(AUTHTYPE_SRP) &&
  2710.                  parsedat[i] == AUTHTYPE_SRP
  2711. #ifdef SRPDLL
  2712.                  && hSRP
  2713. #endif /* SRPDLL */
  2714. #ifdef NO_FTP_AUTH
  2715.                  && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2716. #endif /* NO_FTP_AUTH */
  2717.                  ) {
  2718.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2719.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2720. #ifdef PRE_SRP_1_4_5
  2721.                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2722.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2723.                     continue;
  2724. #endif /* PRE_SRP_1_4_5 */
  2725.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2726.              AUTH_ENCRYPT_USING_TELOPT) &&
  2727.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2728.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2729.                     continue;
  2730.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2731.              AUTH_ENCRYPT_START_TLS) &&
  2732.                      (!ck_ssleay_is_installed()
  2733. #ifdef CK_SSL
  2734.                        || !(tls_active_flag || ssl_active_flag)
  2735. #endif /* CK_SSL */
  2736.                        ))
  2737.                     continue;
  2738.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2739. #ifdef CK_ENCRYPTION
  2740.                     if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2741.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2742.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2743.                     }
  2744. #endif /* CK_ENCRYPTION */
  2745. #ifdef CK_SSL
  2746.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2747.                      ck_ssleay_is_installed() &&
  2748.                      (tls_active_flag || ssl_active_flag) ) {
  2749.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2750.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2751.                 }
  2752. #endif /* CK_SSL */
  2753.                     authentication_version = AUTHTYPE_SRP;
  2754.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2755.                     break;
  2756.                 }
  2757.             }
  2758. #endif /* SRP */
  2759. #ifdef GSSAPI_KRB5
  2760.         if (atok(AUTHTYPE_GSSAPI_KRB5) &&
  2761.             parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
  2762.             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2763.         AUTH_ENCRYPT_AFTER_EXCHANGE &&
  2764. #ifdef OS2
  2765.             hGSSAPI &&
  2766. #endif /* OS2 */
  2767. #ifdef NO_FTP_AUTH
  2768.             strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2769. #endif /* NO_FTP_AUTH */
  2770.             ck_gssapi_is_installed() && !gssk5_msg)
  2771.         {
  2772.             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2773.                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2774.                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
  2775.             {
  2776.                 /* If we are auto-getting TGTs, try */
  2777.                 if ( !ck_krb5_is_tgt_valid() ) {
  2778.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2779.                 }
  2780.                 gssk5_msg = 1;
  2781.             }
  2782.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2783.                       AUTH_CLIENT_TO_SERVER &&
  2784.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2785.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2786. #ifdef CK_ENCRYPTION
  2787.                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
  2788.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2789.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2790.                 }
  2791. #endif /* CK_ENCRYPTION */
  2792.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2793.                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
  2794.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2795.                 break;
  2796.             }
  2797.         }
  2798. #endif /* GSSAPI_KRB5 */
  2799. #ifdef KRB5
  2800.             if ( atok(AUTHTYPE_KERBEROS_V5) &&
  2801.                  parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2802. #ifdef OS2
  2803.                  hKRB5_32 &&
  2804. #endif /* OS2 */
  2805. #ifdef NO_FTP_AUTH
  2806.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2807. #endif /* NO_FTP_AUTH */
  2808.                  ck_krb5_is_installed() && !krb5_msg) {
  2809.  
  2810.                 /* Without encryption we can't perform mutual authentication */
  2811.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2812.                      !ck_crypt_is_installed())
  2813.                     continue;
  2814.  
  2815.                 /* Skip over entries that request credential forwarding */
  2816.                 /* if we are not forwarding.                            */
  2817.                 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2818.                      (forward_flag &&
  2819.                        ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2820.                     continue;
  2821.  
  2822.                 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2823.                                     parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2824.                                     parsedat[i+1] & INI_CRED_FWD_MASK) )
  2825.                 {
  2826.                     /* If we are auto-getting TGTs, try */
  2827.                     if ( !ck_krb5_is_tgt_valid() ) {
  2828.                         printf(
  2829.                "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2830.                     }
  2831.                     krb5_msg = 1;
  2832.                 }
  2833.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2834.                           AUTH_CLIENT_TO_SERVER &&
  2835.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2836.                 {
  2837.                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2838.              AUTH_ENCRYPT_USING_TELOPT) &&
  2839.                          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2840.                            TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2841.                         continue;
  2842.                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2843.              AUTH_ENCRYPT_START_TLS) &&
  2844.                          (!ck_ssleay_is_installed()
  2845. #ifdef CK_SSL
  2846.                            || !(tls_active_flag || ssl_active_flag)
  2847. #endif /* CK_SSL */
  2848.                            ))
  2849.                         continue;
  2850.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2851. #ifdef CK_ENCRYPTION
  2852.                     if (auth_crypt) {
  2853.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2854.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2855.                     }
  2856. #endif /* CK_ENCRYPTION */
  2857. #ifdef CK_SSL
  2858.                     if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2859.                          ck_ssleay_is_installed() &&
  2860.                          (tls_active_flag || ssl_active_flag) ) {
  2861.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2862.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2863.                     }
  2864. #endif /* CK_SSL */
  2865.                     authentication_version = AUTHTYPE_KERBEROS_V5;
  2866.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2867.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2868.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2869.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2870.                     }
  2871.                     break;
  2872.                 }
  2873.             }
  2874. #endif /* KRB5 */
  2875. #ifdef KRB4
  2876.             if ( atok(AUTHTYPE_KERBEROS_V4) &&
  2877.                  parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2878. #ifdef OS2
  2879.                  hKRB4_32 &&
  2880. #endif /* OS2 */
  2881. #ifdef NO_FTP_AUTH
  2882.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2883. #endif /* NO_FTP_AUTH */
  2884.                  ck_krb4_is_installed() && !krb4_msg) {
  2885.                 int rc = 0;
  2886.  
  2887.                 /* Without encryption we can't perform mutual authentication */
  2888.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2889.                      !ck_crypt_is_installed())
  2890.                     continue;
  2891.  
  2892.                 if ( !k4_auth_send() )
  2893.                 {
  2894.                     /* If we are auto-getting TGTs, try */
  2895.                     if ( !ck_krb4_is_tgt_valid() ) {
  2896.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2897.                     }
  2898.                     krb4_msg = 1;
  2899.                 }
  2900.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2901.                           AUTH_CLIENT_TO_SERVER &&
  2902.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2903.                 {
  2904. #ifdef CK_ENCRYPTION
  2905.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2906.             (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2907.              TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2908.               continue;
  2909.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2910.                     if (auth_crypt) {
  2911.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2912.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2913.                     }
  2914. #endif /* CK_ENCRYPTION */
  2915.                     authentication_version = AUTHTYPE_KERBEROS_V4;
  2916.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2917.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2918.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2919.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2920.                     }
  2921.                     break;
  2922.                 }
  2923.             }
  2924. #endif /* KRB4 */
  2925. #ifdef NTLM
  2926.         if ( atok(AUTHTYPE_NTLM) &&
  2927.              parsedat[i] == AUTHTYPE_NTLM &&
  2928.              ck_ntlm_is_valid(1) &&
  2929.              ntlm_auth_send() == 0) {
  2930.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2931.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2932. #ifdef CK_ENCRYPTION
  2933.                 /* NTLM does not support Telnet Encryption */
  2934.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2935.                     continue;
  2936.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2937. #endif /* CK_ENCRYPTION */
  2938.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2939.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2940.                 authentication_version = AUTHTYPE_NTLM;
  2941.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2942.                 break;
  2943.             }
  2944.         }
  2945. #endif /* NTLM */
  2946.         }
  2947.     }
  2948.  
  2949.     if (auth_how == -1) {               /* Did we find one? */
  2950.         switch ( auth_type_user[0] ) {  /* If not, abort the negotiation */
  2951.         case AUTHTYPE_NULL:
  2952.             auth_abort("User refused to accept any authentication method",0);
  2953.             break;
  2954.         case AUTHTYPE_AUTO:
  2955.             auth_abort("No authentication method available", 0);
  2956.             break;
  2957.         default: {
  2958.             char msg[80];
  2959.             ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]),
  2960.                       " could not be negotiated",NULL,NULL
  2961.                      );
  2962.             auth_abort(msg, 0);
  2963.         }
  2964.         }
  2965.         auth_finished(AUTH_REJECT);
  2966.         return AUTH_FAILURE;
  2967.     }
  2968.  
  2969.     printf("Authenticating with %s\r\n",
  2970.             AUTHTYPE_NAME(authentication_version));
  2971.  
  2972.     /* Send Telnet Auth Name message (if necessary) */
  2973.     switch ( authentication_version ) {
  2974.     case AUTHTYPE_SRP:
  2975.     case AUTHTYPE_KERBEROS_V4:
  2976.     case AUTHTYPE_KERBEROS_V5:
  2977.     case AUTHTYPE_GSSAPI_KRB5:
  2978.         /* if we do not have a name to login with get one now. */
  2979.         while ( szUserName[0] == '\0' ) {
  2980.             extern char * tn_pr_uid;
  2981.             readtext(tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
  2982.                       szUserName,63);
  2983.         }
  2984.         plen = strlen(szUserName);
  2985.         pname = (unsigned char *) szUserName;
  2986.  
  2987.         /* Construct Telnet Debugging Message */
  2988.         if (deblog || tn_deb || debses) {
  2989.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  2990.                        "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2991.                        " NAME ",pname," IAC SE",NULL,
  2992.                        NULL,NULL,NULL,NULL,NULL,NULL
  2993.                      );
  2994.             debug(F100,tn_msg,"",0);
  2995.             if (tn_deb || debses) tn_debug(tn_msg);
  2996.         }
  2997.  
  2998.         /* Construct and send Authentication Name subnegotiation */
  2999.         if ( plen < sizeof(buf) - 6 ) {
  3000.             sprintf(buf, "%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  3001.                      TELQUAL_NAME);
  3002.             memcpy(&buf[4], pname, plen);               /* safe */
  3003.             sprintf(&buf[plen + 4], "%c%c", IAC, SE);   /* safe */
  3004.             ttol((CHAR *)buf, plen+6);
  3005.         } else {
  3006.             sprintf(buf, "%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  3007.                      TELQUAL_NAME, IAC, SE);    /* safe */
  3008.             ttol((CHAR *)buf, 6);
  3009.         }
  3010.     }
  3011.  
  3012.     /* Construct Authentication Mode subnegotiation message (if necessary) */
  3013.     switch ( authentication_version ) {
  3014.     case AUTHTYPE_SRP:
  3015.     case AUTHTYPE_KERBEROS_V4:
  3016.     case AUTHTYPE_KERBEROS_V5:
  3017.     case AUTHTYPE_GSSAPI_KRB5:
  3018.     case AUTHTYPE_NTLM:
  3019.         mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt
  3020. #ifdef USE_INI_CRED_FWD
  3021.                | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
  3022.                   auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  3023. #endif /* USE_INI_CRED_FWD */
  3024.                ;
  3025.         sprintf(buf, "%c%c%c%c%c%c%c",
  3026.                  IAC, SB, TELOPT_AUTHENTICATION,
  3027.                  TELQUAL_IS,
  3028.                  authentication_version,
  3029.                  mode,
  3030.                  KRB_AUTH);     /* safe */
  3031.         break;
  3032.     }
  3033.  
  3034.     /* Send initial authentication data */
  3035.     switch ( authentication_version ) {
  3036. #ifdef CK_SSL
  3037.     case AUTHTYPE_SSL:
  3038.         SendSSLAuthSB(SSL_START,NULL,0);
  3039.         break;
  3040. #endif /* SSL */
  3041. #ifdef CK_SRP
  3042.     case AUTHTYPE_SRP:
  3043.         sprintf(&buf[7], "%c%c", IAC, SE);      /* safe */
  3044.         if (deblog || tn_deb || debses) {
  3045.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3046.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  3047.                       " IS ",AUTHTYPE_NAME(authentication_version),
  3048.                       " AUTH ",AUTHMODE_NAME(mode)," IAC SE",
  3049.                       NULL,NULL,NULL,NULL,NULL
  3050.                      );
  3051.             debug(F100,tn_msg,"",0);
  3052.             if (tn_deb || debses) tn_debug(tn_msg);
  3053.         }
  3054.         ttol((CHAR *)buf, 9);
  3055.         break;
  3056. #endif /* SRP */
  3057. #ifdef NTLM
  3058.     case AUTHTYPE_NTLM: {
  3059.         int length = 0;
  3060.  
  3061.         for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) {
  3062.             if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC )
  3063.                 iaccnt++;
  3064.         }
  3065.  
  3066.         if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10)  <
  3067.              sizeof(buf) ) {
  3068.             length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],
  3069.                                    2*sizeof(ULONG));
  3070.             length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
  3071.                                   NTLMSecBuf[0].cbBuffer);
  3072.         }
  3073.         sprintf(&buf[7+length], "%c%c", IAC, SE);
  3074.  
  3075.         if (deblog || tn_deb || debses) {
  3076.             int i;
  3077.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3078.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  3079.                       " IS ",AUTHTYPE_NAME(authentication_version)," ",
  3080.                       AUTHMODE_NAME(mode)," NTLM_AUTH ",
  3081.                        NULL,NULL,NULL,NULL,NULL
  3082.                       );
  3083.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],length);
  3084.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3085.             debug(F100,tn_msg,"",0);
  3086.             if (tn_deb || debses) tn_debug(tn_msg);
  3087.         }
  3088.         ttol((CHAR *)buf, length+9);
  3089.         break;
  3090.     }
  3091. #endif /* NTLM */
  3092. #ifdef KRB4
  3093.     case AUTHTYPE_KERBEROS_V4:
  3094.         for ( i=0 ; i<k4_auth.length ; i++ ) {
  3095.             if ( k4_auth.dat[i] == IAC )
  3096.                 iaccnt++;
  3097.         }
  3098.  
  3099.         if ( k4_auth.length + iaccnt + 10 < sizeof(buf) )
  3100.       k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
  3101.         else
  3102.             k4_auth.length = 0;
  3103.         sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
  3104.  
  3105.         if (deblog || tn_deb || debses) {
  3106.             int i;
  3107.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3108.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3109.                       AUTHTYPE_NAME(authentication_version)," ",
  3110.                       AUTHMODE_NAME(mode)," AUTH ",
  3111.                       NULL,NULL,NULL,NULL,NULL
  3112.                      );
  3113.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length);
  3114.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3115.             debug(F100,tn_msg,"",0);
  3116.             if (tn_deb || debses) tn_debug(tn_msg);
  3117.         }
  3118.         ttol((CHAR *)buf, k4_auth.length+9);
  3119.  
  3120. #ifndef REMOVE_FOR_EXPORT
  3121. #ifdef CK_ENCRYPTION
  3122.         /*
  3123.          * If we are doing mutual authentication, get set up to send
  3124.          * the challenge, and verify it when the response comes back.
  3125.          */
  3126.         if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  3127.             register int i;
  3128.             int rc = 0;
  3129.  
  3130. #ifdef MIT_CURRENT
  3131.             data.data = cred.session;
  3132.             data.length = 8; /* sizeof(cred.session) */;
  3133.  
  3134.             if (code = krb5_c_random_seed(k5_context, &data)) {
  3135.                 com_err("libtelnet", code,
  3136.                          "while seeding random number generator");
  3137.                 return(0);
  3138.             }
  3139.  
  3140.             if (code = krb5_c_make_random_key(k5_context,
  3141.                                                ENCTYPE_DES_CBC_RAW,
  3142.                                                &random_key)) {
  3143.                 com_err("libtelnet", code,
  3144.                          "while creating random session key");
  3145.                 return(0);
  3146.             }
  3147.  
  3148.             /* the krb4 code uses ecb mode, but on a single block
  3149.             with a zero ivec, ecb and cbc are the same */
  3150.             k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  3151.             k4_krbkey.length = 8;
  3152.             k4_krbkey.contents = cred.session;
  3153.  
  3154.             encdata.ciphertext.data = random_key.contents;
  3155.             encdata.ciphertext.length = random_key.length;
  3156.             encdata.enctype = ENCTYPE_UNKNOWN;
  3157.  
  3158.             data.data = k4_session_key;
  3159.             data.length = 8;
  3160.  
  3161.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3162.                                    &encdata, &data);
  3163.  
  3164.             krb5_free_keyblock_contents(k5_context, &random_key);
  3165.  
  3166.             if (code) {
  3167.                 com_err("libtelnet", code, "while encrypting random key");
  3168.                 return(0);
  3169.             }
  3170.  
  3171.             encdata.ciphertext.data = k4_session_key;
  3172.             encdata.ciphertext.length = 8;
  3173.             encdata.enctype = ENCTYPE_UNKNOWN;
  3174.  
  3175.             data.data = k4_challenge;
  3176.             data.length = 8;
  3177.  
  3178.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3179.                                    &encdata, &data);
  3180. #else /* MIT_CURRENT */
  3181.             memset(k4_sched,0,sizeof(Schedule));
  3182.             hexdump("auth_send",cred.session,8);
  3183.             rc = des_key_sched(cred.session, k4_sched);
  3184.             if ( rc == -1 ) {
  3185.                 printf("?Invalid DES key specified in credentials\r\n");
  3186.                 debug(F110,"auth_send",
  3187.               "invalid DES Key specified in credentials",0);
  3188.             } else if ( rc == -2 ) {
  3189.                 printf("?Weak DES key specified in credentials\r\n");
  3190.                 debug(F110,"auth_send",
  3191.               "weak DES Key specified in credentials",0);
  3192.             } else if ( rc != 0 ) {
  3193.                 printf("?DES Key Schedule not set by credentials\r\n");
  3194.                 debug(F110,"auth_send",
  3195.               "DES Key Schedule not set by credentials",0);
  3196.             }
  3197.             hexdump("auth_send schedule",k4_sched,8*16);
  3198.  
  3199.             des_set_random_generator_seed(cred.session);
  3200.  
  3201.             do {
  3202.                 des_new_random_key(k4_session_key);
  3203.                 des_fixup_key_parity(k4_session_key);
  3204.             } while ( ck_des_is_weak_key(k4_session_key) );
  3205.  
  3206.             hexdump("auth_send des_new_random_key(k4_session_key)",
  3207.                      k4_session_key,8);
  3208.  
  3209.             /* Decrypt the session key so that we can send it to the */
  3210.             /* host as a challenge                                   */
  3211. #ifdef NT
  3212.             des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
  3213. #else /* NT */
  3214.             des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
  3215. #endif /* NT */
  3216.         hexdump(
  3217.         "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
  3218.                 k4_session_key,8
  3219.             );
  3220.             /* Prepare the result of the challenge */
  3221.             /* Decrypt the session_key, add 1, and then encrypt it */
  3222.             /* The result stored in k4_challenge should match the  */
  3223.             /* KRB4_RESPONSE value from the host.                  */
  3224. #ifdef NT
  3225.             des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
  3226. #else /* NT */
  3227.             des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
  3228. #endif /* NT */
  3229.  
  3230.             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
  3231.                      k4_challenge,8);
  3232. #endif /* MIT_CURRENT */
  3233.             /*
  3234.             * Increment the challenge by 1, and encrypt it for
  3235.             * later comparison.
  3236.             */
  3237.             for (i = 7; i >= 0; --i) {
  3238.                 register int x;
  3239.                 x = (unsigned int)k4_challenge[i] + 1;
  3240.                 k4_challenge[i] = x;    /* ignore overflow */
  3241.                 if (x < 256)            /* if no overflow, all done */
  3242.                     break;
  3243.             }
  3244.             hexdump("auth_send k4_challenge+1",k4_challenge,8);
  3245. #ifdef MIT_CURRENT
  3246.             data.data = k4_challenge;
  3247.             data.length = 8;
  3248.  
  3249.             encdata.ciphertext.data = k4_challenge;
  3250.             encdata.ciphertext.length = 8;
  3251.             encdata.enctype = ENCTYPE_UNKNOWN;
  3252.  
  3253.             if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
  3254.                                        &encdata)) {
  3255.                 com_err("libtelnet", code, "while encrypting random key");
  3256.                 return(0);
  3257.             }
  3258. #else /* MIT_CURRENT */
  3259. #ifdef NT
  3260.             des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  3261. #else /* NT */
  3262.             des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  3263. #endif /* NT */
  3264.             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
  3265.                      k4_challenge,8);
  3266. #endif /* MIT_CURRENT */
  3267.         }
  3268. #endif  /* ENCRYPTION */
  3269. #endif /* REMOVE_FOR_EXPORT */
  3270.         break;
  3271. #endif /* KRB4 */
  3272. #ifdef GSSAPI_KRB5
  3273.     case AUTHTYPE_GSSAPI_KRB5:
  3274.         for ( i=0 ; i<gss_send_tok.length ; i++ ) {
  3275.             if ( ((char *)gss_send_tok.value)[i] == IAC )
  3276.                 iaccnt++;
  3277.         }
  3278.  
  3279.         if ( gss_send_tok.length + iaccnt + 10 < sizeof(buf) )
  3280.             gss_send_tok.length = copy_for_net(&buf[7], gss_send_tok.value,
  3281.                                                gss_send_tok.length);
  3282.         else
  3283.             gss_send_tok.length = 0;
  3284.         sprintf(&buf[gss_send_tok.length+7], "%c%c", IAC, SE);       /* safe */
  3285.         if (deblog || tn_deb || debses) {
  3286.             int i;
  3287.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3288.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3289.                       AUTHTYPE_NAME(authentication_version)," ",
  3290.                       AUTHMODE_NAME(mode)," AUTH ",
  3291.                       NULL,NULL,NULL,NULL,NULL
  3292.                      );
  3293.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],gss_send_tok.length);
  3294.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3295.             debug(F100,tn_msg,"",0);
  3296.             if (tn_deb || debses) tn_debug(tn_msg);
  3297.         }
  3298.         ttol((CHAR *)buf, gss_send_tok.length+9);
  3299.         break;
  3300. #endif /* GSSAPI_KRB5 */
  3301. #ifdef KRB5
  3302.     case AUTHTYPE_KERBEROS_V5:
  3303.         debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
  3304.         for ( i=0 ; i<k5_auth.length ; i++ ) {
  3305.             if ( ((char *)k5_auth.data)[i] == IAC )
  3306.                 iaccnt++;
  3307.         }
  3308.  
  3309.         if ( k5_auth.length + iaccnt + 10 < sizeof(buf) )
  3310.       k5_auth.length = copy_for_net(&buf[7], k5_auth.data, k5_auth.length);
  3311.         else {
  3312.           debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
  3313.       k5_auth.length = 0;
  3314.         }
  3315.  
  3316.         sprintf(&buf[k5_auth.length+7], "%c%c", IAC, SE);       /* safe */
  3317.         if (deblog || tn_deb || debses) {
  3318.             int i;
  3319.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3320.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3321.                       AUTHTYPE_NAME(authentication_version)," ",
  3322.                       AUTHMODE_NAME(mode)," AUTH ",
  3323.                       NULL,NULL,NULL,NULL,NULL
  3324.                      );
  3325.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
  3326.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3327.             debug(F100,tn_msg,"",0);
  3328.             if (tn_deb || debses) tn_debug(tn_msg);
  3329.         }
  3330.         ttol((CHAR *)buf, k5_auth.length+9);
  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. void
  3688. auth_finished(result) int result; {
  3689.     extern char uidbuf[];
  3690.     extern int sstelnet;
  3691.  
  3692.     validUser = result;
  3693.     switch (result) {
  3694.     case AUTH_REJECT:           /* Rejected */
  3695.         if (sstelnet)
  3696.             uidbuf[0] = '\0';
  3697.         authentication_version = AUTHTYPE_NULL;
  3698.         break;
  3699.     case AUTH_UNKNOWN:          /* We don't know who he is, but he's okay */
  3700.         if (sstelnet)
  3701.             strcpy(uidbuf,"(unknown)");
  3702.         break;
  3703.     case AUTH_OTHER:            /* We know him, but not his name */
  3704.         if (sstelnet)
  3705.             strcpy(uidbuf,"(other)");
  3706.         break;
  3707.     case AUTH_USER:             /* We know he name */
  3708.     case AUTH_VALID:            /* We know him, and he needs no password */
  3709.         if (sstelnet)
  3710.             strcpy(uidbuf,szUserNameRequested);
  3711.         break;
  3712.     }
  3713. }
  3714.  
  3715. #ifdef KRB4
  3716. #ifdef NT
  3717. void
  3718. ck_krb4_debug(int x)
  3719. {
  3720.     set_krb_debug(x);
  3721.     set_krb_ap_req_debug(x);
  3722. }
  3723. #endif /* NT */
  3724. int
  3725. ck_krb4_autoget_TGT(char * realm)
  3726. {
  3727.     extern struct krb_op_data krb_op;
  3728.     extern struct krb4_init_data krb4_init;
  3729.     char passwd[PWD_SZ];
  3730.     char prompt[256];
  3731.     char * saverealm=NULL;
  3732.     int  rc = -1;
  3733.     extern char * k4prprompt;
  3734.     extern char * k4pwprompt;
  3735.  
  3736.     ini_kerb();         /* Place defaults in above structs */
  3737.     passwd[0] = '\0';
  3738.  
  3739.     if ( krb4_init.principal == NULL ||
  3740.          krb4_init.principal[0] == '\0') {
  3741.         readtext(k4prprompt && k4prprompt[0] ?
  3742.          k4prprompt :
  3743.          "Kerberos 4 Principal: ",
  3744.          passwd,PWD_SZ-1);
  3745.         if ( passwd[0] )
  3746.             makestr(&krb4_init.principal,passwd);
  3747.         else
  3748.             return(0);
  3749.     }
  3750.  
  3751.     /* Save realm in init structure so it can be restored */
  3752.     if ( realm ) {
  3753.         saverealm = krb4_init.realm;
  3754.         krb4_init.realm = realm;
  3755.     }
  3756.  
  3757.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  3758.  
  3759.         if ( k4pwprompt && k4pwprompt[0] &&
  3760.              (strlen(k4pwprompt) + strlen(krb4_init.principal) +
  3761.                strlen(krb4_init.realm) - 4) < sizeof(prompt)) {
  3762.             sprintf(prompt,k4pwprompt,krb4_init.principal,krb4_init.realm);
  3763.         } else
  3764.             ckmakxmsg(prompt,sizeof(prompt),
  3765.                   "Kerberos 4 Password for ",krb4_init.principal,"@",
  3766.                   krb4_init.realm,": ",
  3767.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  3768.         readpass(prompt,passwd,PWD_SZ-1);
  3769.     } else {
  3770.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  3771. #ifdef OS2
  3772.         if ( pwcrypt )
  3773.             ck_encrypt((char *)passwd);
  3774. #endif /* OS2 */
  3775.     }
  3776.  
  3777.     if ( passwd[0] ) {
  3778.         makestr(&krb4_init.password,passwd);
  3779.         rc = ck_krb4_initTGT(&krb_op, &krb4_init);
  3780.         free(krb4_init.password);
  3781.         krb4_init.password = NULL;
  3782.     }
  3783.  
  3784.     krb4_init.password = NULL;
  3785.     memset(passwd,0,PWD_SZ);
  3786.  
  3787.     /* restore realm to init structure if needed */
  3788.     if ( saverealm )
  3789.         krb4_init.realm = saverealm;
  3790.     return(rc == 0);
  3791. }
  3792.  
  3793. char *
  3794. ck_krb4_realmofhost(char *host)
  3795. {
  3796.     return (char *)krb_realmofhost(host);
  3797. }
  3798.  
  3799. /*
  3800.  *
  3801.  * K4_auth_send - gets authentication bits we need to send to KDC.
  3802.  *
  3803.  * Result is left in auth
  3804.  *
  3805.  * Returns: 0 on failure, 1 on success
  3806.  */
  3807. static int
  3808. #ifdef CK_ANSIC
  3809. k4_auth_send(void)
  3810. #else
  3811. k4_auth_send()
  3812. #endif
  3813. {
  3814.     int r=0;                                    /* Return value */
  3815.     char instance[INST_SZ+1]="";
  3816.     char *realm=NULL;
  3817.     char tgt[4*REALM_SZ+1];
  3818.  
  3819.     memset(instance, 0, sizeof(instance));
  3820.  
  3821. #ifdef COMMENT
  3822.     /* we only need to call krb_get_phost if the hostname */
  3823.     /* is not fully qualified.  But we have already done  */
  3824.     /* this in netopen() call.  This will save a round of */
  3825.     /* DNS queries.                                       */
  3826.     debug(F110,"k4_auth_send","krb_get_phost",0);
  3827.     if (realm = (char *)krb_get_phost(szHostName)) {
  3828.         ckstrncpy(instance, realm, INST_SZ);
  3829.     }
  3830. #else /* COMMENT */
  3831.     {
  3832.         char *p;
  3833.         ckstrncpy(instance, szHostName, INST_SZ);
  3834.         for ( p=instance; *p && *p != '.' ; p++ );
  3835.         *p = '\0';
  3836.     }
  3837. #endif /* COMMENT */
  3838.  
  3839.     debug(F110,"k4_auth_send","krb_get_realmofhost",0);
  3840.     realm = (char *)krb_realmofhost(szHostName);
  3841.  
  3842.     if (!realm) {
  3843.         strcpy(strTmp, "Can't find realm for host \"");
  3844.         ckstrncat(strTmp, szHostName,AUTHTMPBL);
  3845.         ckstrncat(strTmp, "\"",AUTHTMPBL);
  3846.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3847.         krb4_errno = r;
  3848.         makestr(&krb4_errmsg,strTmp);
  3849.         return(0);
  3850.     }
  3851.  
  3852.     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
  3853.     r = ck_krb4_tkt_isvalid(tgt);
  3854.  
  3855.     if ( r <= 0 && krb4_autoget )
  3856.         ck_krb4_autoget_TGT(realm);
  3857.  
  3858.     debug(F110,"k4_auth_send","krb_mk_req",0);
  3859.     r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3860.                     instance, realm, 0);
  3861.  
  3862.     if (r == 0) {
  3863.         debug(F110,"k4_auth_send","krb_get_cred",0);
  3864.         r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3865.                           instance, realm, (CREDENTIALS *)&cred);
  3866.         if (r)
  3867.             debug(F111,"k4_auth_send","krb_get_cred() failed",r);
  3868.     }
  3869.     else
  3870.         debug(F111,"k4_auth_send","krb_mk_req() failed",r);
  3871.  
  3872.     if (r) {
  3873.         strcpy(strTmp, "Can't get \"");
  3874.         ckstrncat(strTmp,
  3875.           krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,AUTHTMPBL);
  3876.         if (instance[0] != 0) {
  3877.             ckstrncat(strTmp, ".",AUTHTMPBL);
  3878.             ckstrncat(strTmp, instance,AUTHTMPBL);
  3879.         }
  3880.         ckstrncat(strTmp, "@",AUTHTMPBL);
  3881.         ckstrncat(strTmp, realm,AUTHTMPBL);
  3882.         ckstrncat(strTmp, "\" ticket\r\n  ",AUTHTMPBL);
  3883.         ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),AUTHTMPBL);
  3884.         debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
  3885.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3886.         krb4_errno = r;
  3887.         makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3888.         return(0);
  3889.     }
  3890.  
  3891. #ifdef OS2
  3892.     if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
  3893.         ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
  3894.     }
  3895. #endif /* OS2 */
  3896.     krb4_errno = r;
  3897.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3898.     debug(F110,"k4_auth_send",krb4_errmsg,0);
  3899.     return(1);
  3900. }
  3901.  
  3902. /*
  3903.  * Function: K4 parse authentication reply command
  3904.  *
  3905.  * Parameters:
  3906.  *  parsedat - the sub-command data.
  3907.  *
  3908.  *  end_sub - index of the character in the 'parsedat' array which
  3909.  *        is the last byte in a sub-negotiation
  3910.  *
  3911.  * Returns: Kerberos error code.
  3912.  */
  3913. static int
  3914. #ifdef CK_ANSIC
  3915. k4_auth_reply(unsigned char *parsedat, int end_sub)
  3916. #else
  3917. k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3918. #endif
  3919. {
  3920. #ifdef CK_ENCRYPTION
  3921.     Session_Key skey;
  3922. #ifdef MIT_CURRENT
  3923.     krb5_data kdata;
  3924.     krb5_enc_data encdata;
  3925.     krb5_error_code code;
  3926. #endif /* MIT_CURRENT */
  3927. #endif
  3928.     time_t t;
  3929.     int x;
  3930.     int i;
  3931.  
  3932.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  3933.         auth_finished(AUTH_REJECT);
  3934.         return AUTH_FAILURE;
  3935.     }
  3936.  
  3937.     if (parsedat[4] == KRB_REJECT) {
  3938.         strTmp[0] = 0;
  3939.  
  3940.         for (i = 5; i <= end_sub; i++) {
  3941.             if (parsedat[i] == IAC)
  3942.                 break;
  3943.             strTmp[i-5] = parsedat[i];
  3944.             strTmp[i-4] = 0;
  3945.         }
  3946.  
  3947.         if (!strTmp[0])
  3948.             strcpy(strTmp, "Authentication rejected by remote machine!");
  3949.         printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
  3950.         krb4_errno = -1;
  3951.         makestr(&krb4_errmsg,strTmp);
  3952.         auth_finished(AUTH_REJECT);
  3953.         return AUTH_FAILURE;
  3954.     }
  3955.  
  3956.     if (parsedat[4] == KRB_ACCEPT) {
  3957.         int net_len;
  3958.         if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
  3959.             ckmakmsg(strTmp,sizeof(strTmp),"Kerberos V4 accepts you as ",
  3960.                       szUserName,NULL,NULL);
  3961.             printf("%s\r\n",strTmp);
  3962.             accept_complete = 1;
  3963.             krb4_errno = 0;
  3964.             makestr(&krb4_errmsg,strTmp);
  3965.             auth_finished(AUTH_USER);
  3966.             return AUTH_SUCCESS;
  3967.         }
  3968.  
  3969.         if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
  3970.             printf("Kerberos V4 authentication failed!\r\n");
  3971.             ckstrncpy(strTmp,
  3972.         "Kerberos V4 accepted you, but didn't provide mutual authentication",
  3973.                        sizeof(strTmp));
  3974.             printf("%s\r\n",strTmp);
  3975.             krb4_errno = -1;
  3976.             makestr(&krb4_errmsg,strTmp);
  3977.             auth_finished(AUTH_REJECT);
  3978.             return AUTH_FAILURE;
  3979.         }
  3980.  
  3981. #ifndef REMOVE_FOR_EXPORT
  3982. #ifdef CK_ENCRYPTION
  3983.         SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
  3984.  
  3985.         /* We have sent the decrypted session key to the host as a challenge */
  3986.     /* now encrypt it to restore it to its original valid DES key value */
  3987. #ifdef MIT_CURRENT
  3988.         kdata.data = k4_session_key;
  3989.         kdata.length = 8;
  3990.  
  3991.         encdata.ciphertext.data = k4_session_key;
  3992.         encdata.ciphertext.length = 8;
  3993.         encdata.enctype = ENCTYPE_UNKNOWN;
  3994.  
  3995.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
  3996.                                    0, 0, &kdata, &encdata)) {
  3997.             com_err("k4_auth_reply", code,
  3998.                      "while encrypting session_key");
  3999.             auth_finished(AUTH_REJECT);
  4000.             return AUTH_FAILURE;
  4001.         }
  4002. #else /* MIT_CURRENT */
  4003. #ifdef NT
  4004.         des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
  4005. #else /* NT */
  4006.         des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
  4007. #endif /* NT */
  4008.         hexdump(
  4009.         "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
  4010.              k4_session_key,
  4011.          8
  4012.         );
  4013. #endif /* MIT_CURRENT */
  4014.  
  4015. #ifdef CK_SSL
  4016.         if (!(ssl_active_flag || tls_active_flag)) 
  4017. #endif /* CK_SSL */
  4018.         {
  4019.         /* And then use it to configure the encryption state machine. */
  4020.             skey.type = SK_DES;
  4021.             skey.length = 8;
  4022.             skey.data = k4_session_key;
  4023.             encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4024.         }
  4025. #endif /* ENCRYPTION */
  4026. #endif /* REMOVE_FOR_EXPORT */
  4027.         accept_complete = 1;
  4028.         ckmakmsg(strTmp,sizeof(strTmp),
  4029.                  "Kerberos V4 accepts you as ",szUserName,NULL,NULL);
  4030.         printf("%s\r\n",strTmp);
  4031.         krb4_errno = 0;
  4032.         makestr(&krb4_errmsg,strTmp);
  4033.         auth_finished(AUTH_USER);
  4034.         return AUTH_SUCCESS;
  4035.     }
  4036.  
  4037.     if (parsedat[4] == KRB4_RESPONSE) {
  4038.         if (end_sub < 12) {
  4039.             auth_finished(AUTH_REJECT);
  4040.             return AUTH_FAILURE;
  4041.         }
  4042.  
  4043.         hexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
  4044. #ifdef CK_ENCRYPTION
  4045.         hexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
  4046.  
  4047.         /* The datablock returned from the host should match the value */
  4048.         /* we stored in k4_challenge.                                  */
  4049.         if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
  4050.             printf("Kerberos V4 authentication failed!\r\n%s\r\n",
  4051.             "Remote machine is being impersonated!");
  4052.             krb4_errno = -1;
  4053.             makestr(&krb4_errmsg,"Remote machine is being impersonated!");
  4054.             auth_finished(AUTH_REJECT);
  4055.             return AUTH_FAILURE;
  4056.         }
  4057. #else /* ENCRYPTION */
  4058.         makestr(&krb4_errmsg,"Kermit built without support for encryption.");
  4059.         return AUTH_FAILURE;
  4060. #endif /* ENCRYPTION */
  4061.         mutual_complete = 1;
  4062.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  4063.                    sizeof(strTmp));
  4064.         printf("%s\r\n",strTmp);
  4065.         krb4_errno = 0;
  4066.         makestr(&krb4_errmsg,strTmp);
  4067.         auth_finished(AUTH_USER);
  4068.         return AUTH_SUCCESS;
  4069.     }
  4070.     auth_finished(AUTH_REJECT);
  4071.     return AUTH_FAILURE;
  4072. }
  4073.  
  4074. /*
  4075.  * Function: K4 parse authentication IS command
  4076.  *
  4077.  * Parameters:
  4078.  *  parsedat - the sub-command data.
  4079.  *
  4080.  *  end_sub - index of the character in the 'parsedat' array which
  4081.  *            is the last byte in a sub-negotiation
  4082.  *
  4083.  * Returns: Kerberos error code.
  4084.  */
  4085.  
  4086. static int
  4087. #ifdef CK_ANSIC
  4088. k4_auth_is(unsigned char *parsedat, int end_sub)
  4089. #else
  4090. k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  4091. #endif
  4092. {
  4093. #ifdef CK_ENCRYPTION
  4094.     Session_Key skey;
  4095. #ifdef MIT_CURRENT
  4096.     Block datablock, tmpkey;
  4097.     krb5_data kdata;
  4098.     krb5_enc_data encdata;
  4099.     krb5_error_code code;
  4100. #else /* MIT_CURRENT */
  4101.     Block datablock;
  4102. #endif /* MIT_CURRENT */
  4103. #endif    /* ENCRYPTION */
  4104.     char realm[REALM_SZ+1];
  4105.     char instance[INST_SZ];
  4106.     int r = 0;
  4107.     char * data = &parsedat[5];
  4108.     int    cnt = end_sub - 5;
  4109.     extern char myipaddr[];
  4110.     struct hostent *host;
  4111.     struct in_addr inaddr;
  4112.     int i;
  4113.  
  4114.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  4115.         debug(F110,"k4_auth_is","Not kerberos v4",0);
  4116.         auth_finished(AUTH_REJECT);
  4117.         return AUTH_FAILURE;
  4118.     }
  4119.  
  4120.     switch (parsedat[4]) {
  4121.     case KRB_AUTH:
  4122.         debug(F110,"k4_auth_is","KRB_AUTH",0);
  4123.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ+1);
  4124.         if (realm[0] == '\0') {
  4125.             SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
  4126.             printf("\r\n? Kerberos 4 - No Local Realm\r\n");
  4127.             debug(F110,"k4_auth_is","No local realm",0);
  4128.             krb4_errno = -1;
  4129.             makestr(&krb4_errmsg,"No local realm");
  4130.             auth_finished(AUTH_REJECT);
  4131.             return AUTH_FAILURE;
  4132.         }
  4133.         debug(F110,"k4_auth_is",realm,0);
  4134.         if ( cnt < sizeof(k4_auth.dat) ) {
  4135.             k4_auth.length = cnt;
  4136.             memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
  4137.         } else
  4138.             k4_auth.length = 0;
  4139.         hexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
  4140.  
  4141.         /* Get Instance */
  4142.         inaddr.s_addr = inet_addr(myipaddr);
  4143.         host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
  4144.         if ( host ) {
  4145. #ifdef HADDRLIST
  4146.             host = ck_copyhostent(host);
  4147. #endif /* HADDRLIST */
  4148.             ckstrncpy(instance,host->h_name,INST_SZ);
  4149.             for ( i=0;i<INST_SZ;i++ ) {
  4150.                 if ( instance[i] == '.' )
  4151.                     instance[i] = '\0';
  4152.                 else
  4153.                     instance[i] = tolower(instance[i]);
  4154.             }
  4155.         } else {
  4156.             instance[0] = '*';
  4157.             instance[1] = 0;
  4158.         }
  4159.  
  4160.         if (r = krb_rd_req(&k4_auth,
  4161.                             krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  4162.                             instance, 0, &k4_adat, k4_keytab)) {
  4163.  
  4164.             hexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
  4165.             krb_kntoln(&k4_adat, k4_name);
  4166.             ckmakmsg(strTmp,sizeof(strTmp),
  4167.                      "Kerberos failed him as ", k4_name,NULL,NULL);
  4168.             printf("%s\r\n",strTmp);
  4169.             krb4_errno = r;
  4170.             makestr(&krb4_errmsg,strTmp);
  4171.             SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
  4172.             auth_finished(AUTH_REJECT);
  4173.             return AUTH_FAILURE;
  4174.         }
  4175.  
  4176. #ifdef CK_ENCRYPTION
  4177.         memcpy((void *)k4_session_key, (void *)k4_adat.session,
  4178.                 sizeof(Block));                 /* safe */
  4179.         hexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
  4180. #endif /* ENCRYPTION */
  4181.         krb_kntoln(&k4_adat, k4_name);
  4182.  
  4183.         ckstrncpy(szUserNameAuthenticated,k4_name,UIDBUFLEN);
  4184.         if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
  4185.             SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
  4186.         if ( !strcmp(k4_name,szUserNameRequested) )
  4187.         auth_finished(AUTH_VALID);
  4188.         else
  4189.         auth_finished(AUTH_USER);
  4190.             accept_complete = 1;
  4191.         }
  4192.         else {
  4193.             SendK4AuthSB(KRB_REJECT,
  4194.                   (void *)"user is not authorized", -1);
  4195.             auth_finished(AUTH_REJECT);
  4196.             krb4_errno = r;
  4197.             makestr(&krb4_errmsg,"user is not authorized");
  4198.             return(AUTH_FAILURE);
  4199.         }
  4200.         break;
  4201.  
  4202.     case KRB4_CHALLENGE:
  4203.         debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
  4204. #ifndef CK_ENCRYPTION
  4205.         SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  4206. #else    /* ENCRYPTION */
  4207.         if (!VALIDKEY(k4_session_key)) {
  4208.             /*
  4209.             * We don't have a valid session key, so just
  4210.             * send back a response with an empty session
  4211.             * key.
  4212.             */
  4213.             SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  4214.             mutual_complete = 1;
  4215.             break;
  4216.         }
  4217.  
  4218.         /*
  4219.         * Initialize the random number generator since it's
  4220.         * used later on by the encryption routine.
  4221.         */
  4222. #ifdef MIT_CURRENT
  4223.         kdata.data = k4_session_key;
  4224.         kdata.length = 8;
  4225.  
  4226.         if (code = krb5_c_random_seed(k5_context, &kdata)) {
  4227.             com_err("k4_auth_is", code,
  4228.                      "while seeding random number generator");
  4229.             auth_finished(AUTH_REJECT);
  4230.             return AUTH_FAILURE;
  4231.         }
  4232.  
  4233.         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
  4234.         /*
  4235.         * Take the received encrypted challenge, and encrypt
  4236.         * it again to get a unique session_key for the
  4237.         * ENCRYPT option.
  4238.         */
  4239.         k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  4240.         k4_krbkey.length = 8;
  4241.         k4_krbkey.contents = k4_session_key;
  4242.  
  4243.         kdata.data = datablock;
  4244.         kdata.length = 8;
  4245.  
  4246.         encdata.ciphertext.data = tmpkey;
  4247.         encdata.ciphertext.length = 8;
  4248.         encdata.enctype = ENCTYPE_UNKNOWN;
  4249.  
  4250.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  4251.                                    &kdata, &encdata)) {
  4252.             com_err("k4_auth_is", code, "while encrypting random key");
  4253.             auth_finished(AUTH_REJECT);
  4254.             return AUTH_FAILURE;
  4255.         }
  4256.  
  4257. #ifdef CK_SSL
  4258.         if (!(ssl_active_flag || tls_active_flag)) 
  4259. #endif /* CK_SSL */
  4260.         {
  4261.             skey.type = SK_DES;
  4262.             skey.length = 8;
  4263.             skey.data = tmpkey;
  4264.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4265.         }
  4266.         /*
  4267.         * Now decrypt the received encrypted challenge,
  4268.         * increment by one, re-encrypt it and send it back.
  4269.         */
  4270.         encdata.ciphertext.data = datablock;
  4271.         encdata.ciphertext.length = 8;
  4272.         encdata.enctype = ENCTYPE_UNKNOWN;
  4273.  
  4274.         kdata.data = k4_challenge;
  4275.         kdata.length = 8;
  4276.  
  4277.         if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  4278.                                    &encdata, &kdata)) {
  4279.             com_err("k4_auth_is", code, "while decrypting challenge");
  4280.             auth_finished(AUTH_REJECT);
  4281.             return AUTH_FAILURE;
  4282.         }
  4283. #else /* MIT_CURRENT */
  4284.         des_set_random_generator_seed(k4_session_key);
  4285.         r = des_key_sched(k4_session_key, k4_sched);
  4286.         if ( r == -1 ) {
  4287.             printf("?Invalid DES key specified in credentials\r\n");
  4288.             debug(F110,"auth_is CHALLENGE",
  4289.                    "invalid DES Key specified in credentials",0);
  4290.         } else if ( r == -2 ) {
  4291.             printf("?Weak DES key specified in credentials\r\n");
  4292.             debug(F110,"auth_is CHALLENGE",
  4293.                    "weak DES Key specified in credentials",0);
  4294.         } else if ( r != 0 ) {
  4295.             printf("?DES Key Schedule not set by credentials\r\n");
  4296.             debug(F110,"auth_is CHALLENGE",
  4297.                    "DES Key Schedule not set by credentials",0);
  4298.         }
  4299.         hexdump("auth_is schedule",k4_sched,8*16);
  4300.  
  4301.         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
  4302.         hexdump("auth_is challege",datablock,sizeof(Block));
  4303.  
  4304.         /*
  4305.         * Take the received encrypted challenge, and encrypt
  4306.         * it again to get a unique k4_session_key for the
  4307.         * ENCRYPT option.
  4308.         */
  4309. #ifdef NT
  4310.         des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
  4311. #else /* NT */
  4312.         des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
  4313. #endif /* NT */
  4314.         hexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
  4315.                  k4_session_key,8);
  4316.  
  4317. #ifdef CK_SSL
  4318.         if (!(ssl_active_flag || tls_active_flag)) 
  4319. #endif /* CK_SSL */
  4320.         {
  4321.             skey.type = SK_DES;
  4322.             skey.length = 8;
  4323.             skey.data = k4_session_key;
  4324.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4325.         }
  4326.         /*
  4327.         * Now decrypt the received encrypted challenge,
  4328.         * increment by one, re-encrypt it and send it back.
  4329.         */
  4330. #ifdef NT
  4331.         des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
  4332. #else /* NT */
  4333.         des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
  4334. #endif /* NT */
  4335.         hexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
  4336.                  k4_session_key,8);
  4337. #endif /* MIT_CURRENT */
  4338.         for (r = 7; r >= 0; r--) {
  4339.             register int t;
  4340.             t = (unsigned int)k4_challenge[r] + 1;
  4341.             k4_challenge[r] = t;    /* ignore overflow */
  4342.             if (t < 256)        /* if no overflow, all done */
  4343.                 break;
  4344.         }
  4345.         hexdump("auth_is k4_challenge+1",k4_challenge,8);
  4346.  
  4347. #ifdef MIT_CURRENT
  4348.         kdata.data = k4_challenge;
  4349.         kdata.length = 8;
  4350.  
  4351.         encdata.ciphertext.data = k4_challenge;
  4352.         encdata.ciphertext.length = 8;
  4353.         encdata.enctype = ENCTYPE_UNKNOWN;
  4354.  
  4355.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  4356.                                    &kdata, &encdata)) {
  4357.             com_err("k4_auth_is", code, "while decrypting challenge");
  4358.             auth_finished(AUTH_REJECT);
  4359.             return AUTH_FAILURE;
  4360.         }
  4361. #else /* MIT_CURRENT */
  4362. #ifdef NT
  4363.         des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  4364. #else /* NT */
  4365.         des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  4366. #endif /* NT */
  4367.         hexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
  4368.                  k4_challenge,8);
  4369.  
  4370. #endif /* MIT_CURRENT */
  4371.         SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
  4372. #endif    /* ENCRYPTION */
  4373.         mutual_complete = 1;
  4374.         break;
  4375.  
  4376.     default:
  4377.         if (1)
  4378.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  4379.         SendK4AuthSB(KRB_REJECT, 0, 0);
  4380.         return(AUTH_FAILURE);
  4381.     }
  4382.     krb4_errno = r;
  4383.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  4384.     return(AUTH_SUCCESS);
  4385. }
  4386. #endif /* KRB4 */
  4387.  
  4388. #ifdef KRB5
  4389. int
  4390. ck_krb5_autoget_TGT(char * realm)
  4391. {
  4392.     extern struct krb_op_data krb_op;
  4393.     extern struct krb5_init_data krb5_init;
  4394.     char passwd[PWD_SZ];
  4395.     char prompt[64];
  4396.     char * saverealm=NULL;
  4397.     int  rc = -1;
  4398.     extern char * k5prprompt;
  4399.     extern char * k5pwprompt;
  4400.  
  4401.     ini_kerb();         /* Place defaults in above structs */
  4402.     passwd[0] = '\0';
  4403.  
  4404.     if ( krb5_init.principal == NULL ||
  4405.          krb5_init.principal[0] == '\0') {
  4406.         readtext(k5prprompt && k5prprompt[0] ? k5prprompt :
  4407.                   "Kerberos 5 Principal: ",passwd,PWD_SZ-1);
  4408.         if ( passwd[0] )
  4409.             makestr(&krb5_init.principal,passwd);
  4410.         else
  4411.             return(0);
  4412.     }
  4413.  
  4414.     /* Save realm in init structure so it can be restored */
  4415.     if ( realm ) {
  4416.         saverealm = krb5_init.realm;
  4417.         krb5_init.realm = realm;
  4418.     }
  4419.  
  4420.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  4421.         if ( k5pwprompt && k5pwprompt[0] &&
  4422.              (strlen(k5pwprompt) + strlen(krb5_init.principal) +
  4423.               strlen(krb5_init.realm) - 4) < sizeof(prompt)) {
  4424.             sprintf(prompt,k5pwprompt,krb5_init.principal,krb5_init.realm);
  4425.         } else
  4426.         ckmakxmsg(prompt,sizeof(prompt),
  4427.                   k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  4428.                   "Kerberos 5 Password for ",
  4429.                   krb5_init.principal,"@",krb5_init.realm,": ",
  4430.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL
  4431.                  );
  4432.         readpass(prompt,passwd,PWD_SZ-1);
  4433.     } else {
  4434.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  4435. #ifdef OS2
  4436.         if ( pwcrypt )
  4437.             ck_encrypt((char *)passwd);
  4438. #endif /* OS2 */
  4439.     }
  4440.  
  4441.     if ( passwd[0] ) {
  4442.         extern struct krb4_init_data krb4_init;
  4443.         char * savek4realm=NULL;
  4444.  
  4445.         makestr(&krb5_init.password,passwd);
  4446.  
  4447.         if ( krb5_d_getk4 ) {
  4448.             krb5_init.getk4 = 1;
  4449.             makestr(&krb4_init.principal,krb5_init.principal);
  4450.             makestr(&krb4_init.password,passwd);
  4451.             if ( realm ) {
  4452.                 savek4realm = krb4_init.realm;
  4453.                 krb4_init.realm = realm;
  4454.             }
  4455.             rc = ck_krb5_initTGT(&krb_op, &krb5_init,&krb4_init);
  4456.  
  4457.             if ( savek4realm )
  4458.                 krb4_init.realm = savek4realm;
  4459.             free(krb4_init.password);
  4460.             krb4_init.password = NULL;
  4461.         } else {
  4462.             rc = ck_krb5_initTGT(&krb_op, &krb5_init,NULL);
  4463.         }
  4464.  
  4465.         free(krb5_init.password);
  4466.         krb5_init.password = NULL;
  4467.  
  4468.         memset(passwd,0,PWD_SZ);
  4469.     }
  4470.  
  4471.     /* restore realm to init structure if needed */
  4472.     if ( saverealm )
  4473.         krb5_init.realm = saverealm;
  4474.     return(rc == 0);
  4475. }
  4476.  
  4477. static krb5_error_code
  4478. #ifdef CK_ANSIC
  4479. k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
  4480.                char * cc_name )
  4481. #else  /* CK_ANSIC */
  4482. k5_get_ccache(k5_context, p_ccache, cc_name)
  4483.     krb5_context k5_context;
  4484.     krb5_ccache * p_ccache;
  4485.     char * cc_name;
  4486. #endif /* CK_ANSIC */
  4487. {
  4488.     krb5_error_code r=0;
  4489.     char cc_tmp[CKMAXPATH+1];
  4490.     const char * def_name = NULL;
  4491.  
  4492. #ifndef HEIMDAL
  4493.     if ( cc_name ) {
  4494.         if ( strncmp("FILE:",cc_name,5) &&
  4495.              strncmp("MEMORY:",cc_name,7) &&
  4496.              strncmp("API:",cc_name,4) &&
  4497.              strncmp("STDIO:",cc_name,6))
  4498.             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",cc_name,NULL,NULL);
  4499.         else {
  4500.             ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
  4501.         }
  4502.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  4503.         if (r != 0) {
  4504.             com_err("k5_get_ccache resolving ccache",r,
  4505.                      cc_tmp);
  4506.         }
  4507.     } else if ( krb5_d_cc ) {
  4508.         if ( strncmp("FILE:",krb5_d_cc,5) &&
  4509.              strncmp("MEMORY:",krb5_d_cc,7) &&
  4510.              strncmp("API:",krb5_d_cc,4) &&
  4511.              strncmp("STDIO:",krb5_d_cc,6))
  4512.             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",krb5_d_cc,NULL,NULL);
  4513.         else {
  4514.             ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
  4515.         }
  4516.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  4517.         if (r != 0) {
  4518.             com_err("k5_get_ccache resolving ccache",r,
  4519.                      krb5_d_cc);
  4520.         }
  4521.     } else
  4522. #endif /* HEIMDAL */
  4523.     {
  4524.         if ((r = krb5_cc_default(k5_context, p_ccache))) {
  4525.             com_err("k5_get_ccache",r,"while getting default ccache");
  4526.         }
  4527.     }
  4528.     /* do not set krb5_errno/krb5_errmsg here since the value returned */
  4529.     /* is being passed internally within the krb5 functions.           */
  4530.     return(r);
  4531. }
  4532.  
  4533.  
  4534. char *
  4535. ck_krb5_realmofhost(char *host)
  4536. {
  4537.     char ** realmlist=NULL;
  4538.     krb5_context private_context=NULL;
  4539.     static char * realm = NULL;
  4540.  
  4541.     if ( !host )
  4542.         return NULL;
  4543.  
  4544.     if ( realm ) {
  4545.         free(realm);
  4546.         realm = NULL;
  4547.     }
  4548.  
  4549.     /* create private_context */
  4550.     if (krb5_init_context(&private_context)) {
  4551.         debug(F110,"ck_krb5_realmofhost()","unable to init_context",0);
  4552.         return(NULL);
  4553.     }
  4554.  
  4555.     krb5_get_host_realm(private_context,host,&realmlist);
  4556.     if (realmlist && realmlist[0]) {
  4557.         makestr(&realm,realmlist[0]);
  4558.         krb5_free_host_realm(private_context,realmlist);
  4559.         realmlist = NULL;
  4560.     }
  4561.  
  4562.     if ( private_context ) {
  4563.         krb5_free_context(private_context);
  4564.         private_context = NULL;
  4565.     }
  4566.  
  4567.     if (ckstrchr(realm,'.') == NULL) {
  4568.         int n = 0;
  4569.         char * p = host;
  4570.         while ( (p = ckstrchr(p,'.')) != NULL ) {
  4571.             n++;
  4572.             p++;
  4573.         }
  4574.         if (n == 1) {
  4575.             makestr(&realm,host);
  4576.             ckupper(realm);
  4577.         } else {
  4578.             free(realm);
  4579.             realm = NULL;
  4580.         }
  4581.     }
  4582.     return(realm);
  4583. }
  4584.  
  4585. /*
  4586.  *
  4587.  * K5_auth_send - gets authentication bits we need to send to KDC.
  4588.  *
  4589.  * Code lifted from telnet sample code in the appl directory.
  4590.  *
  4591.  * Result is left in k5_auth
  4592.  *
  4593.  * Returns: 0 on failure, 1 on success
  4594.  *
  4595.  */
  4596.  
  4597. static int
  4598. #ifdef CK_ANSIC
  4599. k5_auth_send(int how, int encrypt, int forward)
  4600. #else
  4601. k5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
  4602. #endif
  4603. {
  4604.     krb5_error_code r=0;
  4605.     krb5_ccache ccache=NULL;
  4606. #ifndef HEIMDAL
  4607.     krb5_creds creds;
  4608. #endif /* HEIMDAL */
  4609.     krb5_creds * new_creds=NULL;
  4610. #ifdef CK_ENCRYPTION
  4611.     krb5_keyblock *newkey = 0;
  4612. #endif /* CK_ENCRYPTION */
  4613.     krb5_flags ap_opts, auth_flags;
  4614.     char type_check[32];
  4615.     krb5_data checksum;
  4616.     int len=0;
  4617.     char * realm = NULL;
  4618.     char tgt[256];
  4619.  
  4620.     realm = ck_krb5_realmofhost(szHostName);
  4621.     if (!realm) {
  4622.         ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
  4623.         ckstrncat(strTmp, szHostName,AUTHTMPBL);
  4624.         ckstrncat(strTmp, "\"",AUTHTMPBL);
  4625.         printf("?Kerberos 5 error: %s\r\n",strTmp);
  4626.         krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
  4627.         makestr(&krb5_errmsg,strTmp);
  4628.         return(0);
  4629.     }
  4630.  
  4631.     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  4632.     debug(F110,"k5_auth_send TGT",tgt,0);
  4633.     if ( krb5_autoget &&
  4634.          !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  4635.       (ck_krb5_is_tgt_valid() > 0)) )
  4636.         ck_krb5_autoget_TGT(realm);
  4637.  
  4638.     r = k5_get_ccache(k5_context,&ccache,NULL);
  4639.     if ( r ) {
  4640.         com_err(NULL, r, "while authorizing (0).");
  4641.         krb5_errno = r;
  4642.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4643.         return(0);
  4644.     }
  4645.  
  4646. #ifndef HEIMDAL
  4647.     memset((char *)&creds, 0, sizeof(creds));
  4648.     if (r = krb5_sname_to_principal(k5_context, szHostName,
  4649.                                 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4650.                                 KRB5_NT_SRV_HST, &creds.server)) {
  4651.         com_err(NULL, r, "while authorizing (1).");
  4652.         krb5_errno = r;
  4653.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4654.         return(0);
  4655.     }
  4656.  
  4657.     if (forward_flag) {
  4658.         if (fwd_server) {
  4659.             krb5_free_principal(k5_context,fwd_server);
  4660.             fwd_server = NULL;
  4661.         }
  4662.         krb5_copy_principal(k5_context,creds.server,&fwd_server);
  4663.     }
  4664.  
  4665.     if (r = krb5_cc_get_principal(k5_context, ccache, &creds.client)) {
  4666.         com_err(NULL, r, "while authorizing (2).");
  4667.         krb5_free_cred_contents(k5_context, &creds);
  4668.         krb5_errno = r;
  4669.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4670.         return(0);
  4671.     }
  4672.  
  4673.     if (szUserName[0] == '\0') {                /* Get user name now */
  4674.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4675.         if ( len < sizeof(szUserName) ) {
  4676.             memcpy(szUserName,
  4677.                     krb5_princ_component(k5_context, creds.client, 0)->data,
  4678.                     len);                       /* safe */
  4679.         } else
  4680.             len = 0;
  4681.         szUserName[len] = '\0';
  4682.     } else {
  4683.         char * name = NULL;
  4684.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4685.         if ( len == strlen(szUserName) ) {
  4686.             name = krb5_princ_component(k5_context, creds.client, 0)->data;
  4687. #ifdef OS2
  4688.             if ( !strnicmp(szUserName,name,len) )
  4689.                 memcpy(szUserName,name,len);    /* safe */
  4690. #endif /* OS2 */
  4691.         }
  4692.     }
  4693.  
  4694.     /* Not sure if this is necessary anymore.  What impact does it have
  4695.      * on Win2000 TGTs that use DES_CBC_MD5 or RC4_HMAC?
  4696.      *
  4697.      * This prevents using 3DES Service Tickets.
  4698.      */
  4699.     creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
  4700.     if (r = krb5_get_credentials(k5_context, 0,
  4701.                                   ccache, &creds, &new_creds)) {
  4702.         com_err(NULL, r, "while authorizing (3).");
  4703.         krb5_free_cred_contents(k5_context, &creds);
  4704.         krb5_errno = r;
  4705.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4706.         return(0);
  4707.     }
  4708. #endif /* HEIMDAL */
  4709.  
  4710.     if (auth_context) {
  4711.         krb5_auth_con_free(k5_context, auth_context);
  4712.         auth_context = 0;
  4713.     }
  4714.     if (r = krb5_auth_con_init(k5_context, &auth_context)) {
  4715.         com_err(NULL, r, "while initializing auth context");
  4716.         krb5_errno = r;
  4717.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4718.         return(0);
  4719.     }
  4720.  
  4721.     /* UPDATE for START_TLS.  AUTH_ENCRYPT_START_TLS and inclusion of */
  4722.     /* client and then server finished messages.                      */
  4723.  
  4724.     type_check[0] = AUTHTYPE_KERBEROS_V5;
  4725.     type_check[1] = AUTH_CLIENT_TO_SERVER |
  4726.         (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
  4727.         (encrypt) |
  4728.         (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
  4729. #ifdef CK_SSL
  4730.     if (encrypt == AUTH_ENCRYPT_START_TLS) {
  4731.         ssl_get_client_finished(&type_check[2],12);
  4732.         ssl_get_server_finished(&type_check[14],12);
  4733.     }
  4734. #endif /* CK_SSL */
  4735.  
  4736. #ifndef HEIMDAL
  4737.     checksum.magic = KV5M_DATA;
  4738. #endif /* HEIMDAL */
  4739.     checksum.length =
  4740. #ifdef CK_SSL
  4741.         (encrypt == AUTH_ENCRYPT_START_TLS) ? 26 :
  4742. #endif /* CK_SSL */
  4743.         2;
  4744.     checksum.data = (char *)&type_check;
  4745.  
  4746.     ap_opts = 0;
  4747.     if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
  4748.         ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
  4749.  
  4750. #ifdef HEIMDAL
  4751.     r = krb5_auth_setkeytype(k5_context, auth_context, KEYTYPE_DES);
  4752.     if (r)
  4753.         com_err(NULL, r, "while setting auth keytype");
  4754.     r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context, &ttyfd);
  4755.     if (r)
  4756.         com_err(NULL, r, "while setting auth addrs");
  4757.     r = krb5_mk_req(k5_context, &auth_context, ap_opts,
  4758.                     krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4759.                     szHostName, &checksum, ccache, &k5_auth);
  4760.     if (r)
  4761.         com_err(NULL, r, "while making request");
  4762. #else /* HEIMDAL */
  4763.     auth_flags = KRB5_AUTH_CONTEXT_RET_TIME;
  4764. #ifdef CK_ENCRYPTION
  4765.     ap_opts |= AP_OPTS_USE_SUBKEY;
  4766. #endif /* CK_ENCRYPTION */
  4767. #ifdef TLS_VERIFY
  4768.     if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  4769.         auth_flags |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
  4770.         if (!krb5_d_no_addresses)
  4771.             r = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  4772.                                  KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
  4773.     }
  4774. #endif /* CK_SSL */
  4775.     krb5_auth_con_setflags(k5_context, auth_context, auth_flags);
  4776.     r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
  4777.                               &checksum, new_creds, &k5_auth);
  4778. #endif /* HEIMDAL */
  4779.  
  4780. #ifdef CK_ENCRYPTION
  4781.     if (!r) {
  4782.         r = krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
  4783.         if (r)
  4784.             r = krb5_auth_con_getkey(k5_context, auth_context, &newkey);
  4785.  
  4786.         if (k5_session_key) {
  4787.             krb5_free_keyblock(k5_context, k5_session_key);
  4788.             k5_session_key = 0;
  4789.         }
  4790.     }
  4791.     if (newkey) {
  4792.         /*
  4793.         * keep the key in our private storage, but don't use it
  4794.         * yet---see kerberos5_reply() below
  4795.         */
  4796. #ifdef HEIMDAL
  4797.         if ((newkey->keytype == ETYPE_DES_CBC_CRC) ||
  4798.              (newkey->keytype == ETYPE_DES_CBC_MD5) ||
  4799.              (newkey->keytype == ETYPE_DES_CBC_MD4))
  4800.         {
  4801.             debug(F111,"k5_auth_send()","newkey->keytype",newkey->keytype);
  4802.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4803.         }
  4804. #else /* HEIMDAL */
  4805.         /* look for all possible DES keys first - just for compatibility */
  4806.         /* other key types are much less likely to be available          */
  4807.         if ((newkey->enctype == ENCTYPE_DES_CBC_CRC) ||
  4808.              (newkey->enctype == ENCTYPE_DES_CBC_MD5) ||
  4809.              (newkey->enctype == ENCTYPE_DES_CBC_MD4))
  4810.         {
  4811.             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
  4812.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4813.         }
  4814.         else if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
  4815.                  (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
  4816.         {
  4817.             /* use the session key in credentials instead */
  4818.             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
  4819.                    new_creds->keyblock.enctype);
  4820.             krb5_copy_keyblock(k5_context,
  4821.                                 &new_creds->keyblock, &k5_session_key);
  4822.         }
  4823.         else if (newkey->enctype != 0)
  4824.         {
  4825.             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
  4826.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4827.         }
  4828.         else if (new_creds->keyblock.enctype != 0)
  4829.         {
  4830.             /* use the session key in credentials instead */
  4831.             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
  4832.                    new_creds->keyblock.enctype);
  4833.             krb5_copy_keyblock(k5_context,
  4834.                                 &new_creds->keyblock, &k5_session_key);
  4835.         }
  4836.         else {
  4837.             debug(F110,"k5_auth_send()","NO KEY in newkey",0);
  4838.         }
  4839. #endif /* HEIMDAL */
  4840.         krb5_free_keyblock(k5_context, newkey);
  4841.     }
  4842. #endif /* CK_ENCRYPTION */
  4843. #ifndef HEIMDAL
  4844.     krb5_free_cred_contents(k5_context, &creds);
  4845.     krb5_free_creds(k5_context, new_creds);
  4846. #endif /* HEIMDAL */
  4847.     krb5_cc_close(k5_context,ccache);
  4848.  
  4849.     if (r) {
  4850.         com_err(NULL, r, "while authorizing (4).");
  4851.         krb5_errno = r;
  4852.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4853.         return(0);
  4854.     }
  4855.     krb5_errno = 0;
  4856.     makestr(&krb5_errmsg,"OK");
  4857.     return(1);
  4858. }
  4859.  
  4860. /*
  4861.  * K5_auth_reply -- checks the reply for mutual authentication.
  4862.  */
  4863. static int
  4864. #ifdef CK_ANSIC
  4865. k5_auth_reply(int how, unsigned char *data, int cnt)
  4866. #else
  4867. k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  4868. #endif
  4869. {
  4870. #ifdef CK_ENCRYPTION
  4871.     Session_Key skey;
  4872. #endif /* CK_ENCRYPTION */
  4873.  
  4874.     data += 4;                                  /* Point to status byte */
  4875.     cnt -=5;
  4876.  
  4877.     switch (*data++) {
  4878.     case KRB_REJECT:
  4879.         if (cnt > 0) {
  4880.             char *s;
  4881.             int len;
  4882.             ckstrncpy(strTmp,"Kerberos V5 refuses authentication because\r\n",
  4883.                       sizeof(strTmp));
  4884.             len = strlen(strTmp);
  4885.             if ( len + cnt < sizeof(strTmp) ) {
  4886.                 s = strTmp + strlen(strTmp);
  4887.                 memcpy(s, data, cnt);           /* safe */
  4888.                 s[cnt] = 0;
  4889.             }
  4890.         } else
  4891.             ckstrncpy(strTmp,"Kerberos V5 refuses authentication",
  4892.                       sizeof(strTmp));
  4893.         krb5_errno = -1;
  4894.         makestr(&krb5_errmsg,strTmp);
  4895.         printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4896.         auth_finished(AUTH_REJECT);
  4897.         return AUTH_FAILURE;
  4898.  
  4899.     case KRB_ACCEPT:
  4900.         if (!mutual_complete) {
  4901.             if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
  4902.                 ckstrncpy(strTmp,
  4903.                           "Kerberos V5 accepted you, but didn't provide"
  4904.                           " mutual authentication",sizeof(strTmp));
  4905.                 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4906.                 krb5_errno = -1;
  4907.                 makestr(&krb5_errmsg,strTmp);
  4908.                 auth_finished(AUTH_REJECT);
  4909.                 return AUTH_FAILURE;
  4910.             }
  4911.  
  4912. #ifdef CK_ENCRYPTION
  4913.             if (k5_session_key) {
  4914.                 /* Even if the session key is 3DES, we must lie because otherwise */
  4915.                 /* we can't negotiate the proper keys for DES encryption if the   */
  4916.                 /* since the host may be requiring SK_DES key choice.             */
  4917.                 skey.type = SK_DES;
  4918.                 skey.length = 8;
  4919. #ifdef HEIMDAL
  4920.                 skey.data = k5_session_key->keyvalue.data;
  4921. #else /* HEIMDAL */
  4922.                 skey.data = k5_session_key->contents;
  4923. #endif /* HEIMDAL */
  4924.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4925.             }
  4926. #endif /* CK_ENCRYPTION */
  4927.         }
  4928.         if ( cnt > 0 ) {
  4929.             char *s;
  4930.             int len;
  4931.             ckstrncpy(strTmp,"Kerberos V5 accepts you as ",sizeof(strTmp));
  4932.             len = strlen(strTmp);
  4933.             if ( len + cnt < sizeof(strTmp) ) {
  4934.                 s = strTmp + strlen(strTmp);
  4935.                 memcpy(s,data,cnt);
  4936.                 s[cnt] = 0;
  4937.             }
  4938.         }
  4939.         accept_complete = 1;
  4940.         printf("%s\r\n",strTmp);
  4941.  
  4942. #ifdef FORWARD
  4943.         if (forward_flag
  4944. #ifdef COMMENT
  4945.              /* Marc Horowitz <marc@mit.edu> has successfully argued
  4946.                 that it is indeed safe to send Forwarded credentials
  4947.                 to an untrusted host.
  4948.               */
  4949.              && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL
  4950. #endif /* COMMENT */
  4951.              )
  4952.             kerberos5_forward();
  4953. #endif /* FORWARD */
  4954.         krb5_errno = 0;
  4955.         makestr(&krb5_errmsg,strTmp);
  4956.         auth_finished(AUTH_USER);
  4957.         return AUTH_SUCCESS;
  4958.  
  4959.     case KRB5_RESPONSE:
  4960. #ifdef TLS_VERIFY
  4961.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
  4962.         !krb5_tls_verified) {
  4963.             printf(
  4964.     "Man in the middle attack detected.  Session terminated.\r\n");
  4965. #ifndef BETATEST
  4966.             netclos();
  4967. #endif /* BETATEST */
  4968.             krb5_errno = -1;
  4969.             makestr(&krb5_errmsg,"TLS not verified");
  4970.             auth_finished(AUTH_REJECT);
  4971.             return AUTH_FAILURE;
  4972.         }
  4973.         if((ssl_active_flag || tls_active_flag) &&
  4974.             (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  4975.             printf("TLS session parameters verified by Kerberos 5\r\n");
  4976.         }
  4977. #endif /* TLS_VERIFY */
  4978.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  4979.             /* the rest of the reply should contain a krb_ap_rep */
  4980.             krb5_ap_rep_enc_part *reply;
  4981.             krb5_data inbuf;
  4982.             krb5_error_code r;
  4983.  
  4984.             inbuf.length = cnt;
  4985.             inbuf.data = (char *)data;
  4986.  
  4987.             if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
  4988.                 com_err(NULL, r, "while authorizing. (5)");
  4989.                 krb5_errno = r;
  4990.                 makestr(&krb5_errmsg,error_message(krb5_errno));
  4991.                 auth_finished(AUTH_REJECT);
  4992.                 return AUTH_FAILURE;
  4993.             }
  4994.             krb5_free_ap_rep_enc_part(k5_context, reply);
  4995.  
  4996. #ifdef CK_ENCRYPTION
  4997.             if (encrypt_flag && k5_session_key) {
  4998.                 /* Even if the session key is 3DES, we must lie because otherwise */
  4999.                 /* we can't negotiate the proper keys for DES encryption if the   */
  5000.                 /* since the host may be requiring SK_DES key choice.             */
  5001.                 skey.type = SK_DES;
  5002.                 skey.length = 8;
  5003. #ifdef HEIMDAL
  5004.                 skey.data = k5_session_key->keyvalue.data;
  5005. #else /* HEIMDAL */
  5006.                 skey.data = k5_session_key->contents;
  5007. #endif /* HEIMDAL */
  5008.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  5009.             }
  5010. #endif /* ENCRYPTION */
  5011.             mutual_complete = 1;
  5012.         }
  5013.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  5014.                   sizeof(strTmp));
  5015.         krb5_errno = 0;
  5016.         makestr(&krb5_errmsg,strTmp);
  5017.         printf("%s\r\n",strTmp);
  5018.         auth_finished(AUTH_USER);
  5019.         return AUTH_SUCCESS;
  5020.  
  5021. #ifdef FORWARD
  5022.     case KRB5_FORWARD_ACCEPT:
  5023.         forwarded_tickets = 1;
  5024.         ckstrncpy(strTmp,"Remote machine has accepted forwarded credentials",
  5025.                   sizeof(strTmp));
  5026.         krb5_errno = 0;
  5027.         makestr(&krb5_errmsg,strTmp);
  5028.         printf("%s\r\n",strTmp);
  5029.         return AUTH_SUCCESS;
  5030.  
  5031.     case KRB5_FORWARD_REJECT:
  5032.         forwarded_tickets = 0;
  5033.         if (cnt > 0) {
  5034.             char *s;
  5035.             int len;
  5036.             len = ckstrncpy(strTmp,
  5037.                       "Kerberos V5 refuses forwarded credentials because ",
  5038.                        sizeof(strTmp));
  5039.             if ( len + cnt < sizeof(strTmp) ) {
  5040.                 s = strTmp + strlen(strTmp);
  5041.                 memcpy(s, data, cnt);
  5042.                 s[cnt] = 0;
  5043.             }
  5044.         } else
  5045.             ckstrncpy(strTmp, "Kerberos V5 refuses forwarded credentials",
  5046.                       sizeof(strTmp));
  5047.  
  5048.         printf("%s\r\n",strTmp);
  5049.         krb5_errno = -1;
  5050.         makestr(&krb5_errmsg,strTmp);
  5051.         return AUTH_SUCCESS;
  5052. #endif    /* FORWARD */
  5053.  
  5054. #ifdef TLS_VERIFY
  5055.     case KRB5_TLS_VERIFY:
  5056.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5057.             krb5_data reply, msg;
  5058.             char tls_verify[24];
  5059.             krb5_replay_data repdata;
  5060.             krb5_error_code r;
  5061.  
  5062.             ssl_get_server_finished(&tls_verify[0],12);
  5063.             ssl_get_client_finished(&tls_verify[12],12);
  5064.  
  5065.             reply.data = data;
  5066.             reply.length = cnt;
  5067.  
  5068.             if (!krb5_d_no_addresses)
  5069.                 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  5070.                   KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
  5071.  
  5072.             if (r = krb5_rd_safe(k5_context,auth_context,&reply,&msg,&repdata))
  5073.           {
  5074.                 com_err("", r, "decoding tls verifier");
  5075.                 krb5_errno = r;
  5076.                 makestr(&krb5_errmsg,"TLS verify failure");
  5077.                 auth_finished(AUTH_REJECT);
  5078.                 return(AUTH_FAILURE);
  5079.             }
  5080.             if ( msg.length == 24 && !memcmp(msg.data,tls_verify,24) )
  5081.                  krb5_tls_verified = 1;
  5082.             krb5_free_data_contents(k5_context,&msg);
  5083.             if (krb5_tls_verified)
  5084.                 return(AUTH_SUCCESS);
  5085.         }
  5086.         printf("Man in the middle attack detected.  Session terminated.\r\n");
  5087.         netclos();
  5088.         krb5_errno = -1;
  5089.         makestr(&krb5_errmsg,"TLS verify failure");
  5090.         auth_finished(AUTH_REJECT);
  5091.         return(AUTH_FAILURE);
  5092. #endif /* CK_SSL */
  5093.  
  5094.     default:
  5095.         krb5_errno = -1;
  5096.         makestr(&krb5_errmsg,"Unknown reply type");
  5097.         auth_finished(AUTH_REJECT);
  5098.         return AUTH_FAILURE;                        /* Unknown reply type */
  5099.     }
  5100. }
  5101.  
  5102. #ifdef FORWARD
  5103. /* Decode, decrypt and store the forwarded creds in the local ccache. */
  5104. /* Needed for KRB5_FORWARD                                            */
  5105. static krb5_error_code
  5106. rd_and_store_for_creds(context, auth_context, inbuf, client)
  5107.     krb5_context context;
  5108.     krb5_auth_context auth_context;
  5109.     krb5_data *inbuf;
  5110.     krb5_const_principal client;
  5111. {
  5112.     krb5_creds ** creds=NULL;
  5113.     krb5_error_code retval;
  5114.     krb5_ccache ccache=NULL;
  5115.  
  5116. #ifdef HEIMDAL
  5117.     /*
  5118.     Heimdal Telnetd creates the cache file at this point and sets
  5119.     the KRB5CCNAME environment variable.
  5120.  
  5121.     struct passwd *pwd;
  5122.     char ccname[1024];
  5123.  
  5124.     pwd = getpwnam(szUserNameRequested);
  5125.     if (pwd == NULL)
  5126.         break;
  5127.     snprintf(ccname, sizeof(ccname)-1, "FILE:/tmp/krb5cc_%u",pwd->pw_uid);
  5128.     retval = krb5_cc_resolve(context,ccname,&ccache);
  5129.  
  5130.     chown(ccname + 5, pwd->pw_uid, -1);
  5131.     */
  5132. #endif /* HEIMDAL */
  5133.  
  5134.     if (retval = k5_get_ccache(context,&ccache,NULL))
  5135.         return(retval);
  5136.  
  5137. #ifdef HEIMDAL
  5138.     if ((retval = krb5_cc_initialize(context, ccache, client)))
  5139.         return(retval);
  5140.  
  5141.     if ((retval = krb5_rd_cred(context, auth_context, ccache, inbuf)))
  5142.         return(retval);
  5143. #else /* HEIMDAL */
  5144.     if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
  5145.         return(retval);
  5146.  
  5147.     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
  5148.         goto cleanup;
  5149.  
  5150.     if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
  5151.         goto cleanup;
  5152.  
  5153.     if ((retval = krb5_cc_close(context, ccache)))
  5154.         goto cleanup;
  5155.  
  5156.   cleanup:
  5157.     krb5_free_tgt_creds(context, creds);
  5158. #endif /* HEIMDAL */
  5159.     return retval;
  5160. }
  5161. #endif /* FORWARD */
  5162.  
  5163. /*
  5164.  *
  5165.  * K5_auth_is.
  5166.  *
  5167.  */
  5168.  
  5169. static int
  5170. #ifdef CK_ANSIC
  5171. k5_auth_is(int how, unsigned char *data, int cnt)
  5172. #else
  5173. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  5174. #endif
  5175. {
  5176.     int r = 0;
  5177.     krb5_principal server;
  5178.     krb5_keyblock *newkey = NULL;
  5179.     krb5_data outbuf;
  5180.     char errbuf[128]="";
  5181.     char *getenv();
  5182. #ifndef HEIMDAL
  5183.     krb5_authenticator *authenticator;
  5184.     krb5_keytab keytabid = 0;
  5185. #endif /* HEIMDAL */
  5186.     krb5_data inbuf;
  5187. #ifdef CK_ENCRYPTION
  5188.     Session_Key skey;
  5189. #endif /* CK_ENCRYPTION */
  5190.     char princ[256]="";
  5191.     int len;
  5192.  
  5193.     data += 4;                                  /* Point to status byte */
  5194.     cnt -= 4;
  5195.  
  5196.     hexdump("k5_auth_is data",data,cnt);
  5197.     debug(F111,"k5_auth_is","how",how);
  5198.  
  5199.     if (cnt-- < 1) {
  5200.         auth_finished(AUTH_REJECT);
  5201.         return AUTH_FAILURE;
  5202.     }
  5203.     switch (*data++) {
  5204.     case KRB_AUTH:
  5205.         k5_auth.data = (char *)data;
  5206.         k5_auth.length = cnt;
  5207.  
  5208.         debug(F110,"k5_auth_is","KRB_AUTH",0);
  5209.         debug(F111,"k5_auth_is","auth_context",auth_context);
  5210.  
  5211.         if (!r && !auth_context) {
  5212.             r = krb5_auth_con_init(k5_context, &auth_context);
  5213.             debug(F111,"k5_auth_is","krb5_auth_con_init",r);
  5214.         }
  5215.  
  5216. #ifdef HEIMDAL
  5217.         if (!r)
  5218.             r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context,&ttyfd);
  5219.  
  5220.         if (!r)
  5221.             r = krb5_sock_to_principal(k5_context,0,"host",
  5222.                                        KRB5_NT_SRV_HST,&server);
  5223.  
  5224.         if (!r)
  5225. #else /* HEIMDAL */
  5226.         if (!r) {
  5227.             krb5_rcache rcache = NULL;
  5228.  
  5229.             r = krb5_auth_con_getrcache(k5_context, auth_context,
  5230.                                          &rcache);
  5231.             debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
  5232.  
  5233.             if (!r && !rcache) {
  5234.                 /* Do not resolve server's principal name, we will check */
  5235.                 /* for validity after the krb5_rd_req() call.            */
  5236.                 r = krb5_sname_to_principal(k5_context, 0, 0,
  5237.                                              KRB5_NT_SRV_HST, &server);
  5238.                 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
  5239.  
  5240.                 if (!r) {
  5241.                     r = krb5_get_server_rcache(k5_context,
  5242.                         krb5_princ_component(k5_context, server, 0),
  5243.                                                 &rcache);
  5244.                     debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
  5245.                     krb5_free_principal(k5_context, server);
  5246.                 }
  5247.             }
  5248.             if (!r) {
  5249.                 r = krb5_auth_con_setrcache(k5_context,
  5250.                                              auth_context, rcache);
  5251.                 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
  5252.             }
  5253.         }
  5254.         if (!r && k5_keytab) {
  5255.             r = krb5_kt_resolve(k5_context,
  5256.                                  k5_keytab, &keytabid);
  5257.             debug(F111,"k5_auth_is","krb5_kt_resolve",r);
  5258.         }
  5259. #endif /* HEIMDAL */
  5260.         if (!r) {
  5261.             r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
  5262. #ifdef HEIMDAL
  5263.                              server, NULL, NULL,
  5264. #else /* HEIMDAL */
  5265.                              NULL, keytabid, NULL,
  5266. #endif /* HEIMDAL */
  5267.                              &k5_ticket);
  5268.             debug(F111,"k5_auth_is","krb5_rd_req",r);
  5269.         }
  5270.         if (r) {
  5271.             (void) ckstrncpy(errbuf, "krb5_rd_req failed: ",sizeof(errbuf));
  5272.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5273.             goto errout;
  5274.         }
  5275. #ifdef HEIMDAL
  5276.         krb5_free_principal(k5_context, server);
  5277.  
  5278.         {
  5279.             char type_check[26];
  5280.  
  5281.             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
  5282.             /* client and then server finished messages. */
  5283.  
  5284.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  5285.             type_check[1] = how;        /* not broken into parts */
  5286. #ifdef CK_SSL
  5287.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5288.                 ssl_get_client_finished(&type_check[2],12);
  5289.                 ssl_get_server_finished(&type_check[14],12);
  5290.                 hexdump("k5_auth_is type_check",type_check,26);
  5291.             }
  5292. #endif /* CK_SSL */
  5293.  
  5294.             r = krb5_verify_authenticator_checksum(k5_context,
  5295.                                                     auth_context,
  5296.                                                     type_check,
  5297. #ifdef CK_SSL
  5298.                 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  5299. #endif /* CK_SSL */
  5300.                                                     2);
  5301.         }
  5302. #else /* HEIMDAL */
  5303.         len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
  5304.         if (len < 256)
  5305.         {
  5306.             memcpy(princ,
  5307.                    krb5_princ_component(k5_context,k5_ticket->server,0)->data,
  5308.                    len);
  5309.             princ[len] = '\0';
  5310.         }
  5311.         if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
  5312.         {
  5313.             debug(F110,"k5_auth_is incorrect service name",princ,0);
  5314.         ckstrncpy(errbuf,"incorrect service name: ",sizeof(errbuf));
  5315.         ckstrncat(errbuf,krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5316.              sizeof(errbuf));
  5317.         ckstrncat(errbuf," != ",sizeof(errbuf));
  5318.         ckstrncat(errbuf,princ,sizeof(errbuf));
  5319.             goto errout;
  5320.         }
  5321.  
  5322.         r = krb5_auth_con_getauthenticator(k5_context,
  5323.                                             auth_context,
  5324.                                             &authenticator);
  5325.         debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
  5326.         if (r) {
  5327.             (void) ckstrncpy(errbuf,
  5328.                  "krb5_auth_con_getauthenticator failed: ",
  5329.                  sizeof(errbuf)
  5330.                  );
  5331.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5332.             goto errout;
  5333.         }
  5334.  
  5335.         if (authenticator->checksum) {
  5336.             char type_check[26];
  5337.             krb5_checksum *cksum = authenticator->checksum;
  5338.             krb5_keyblock *key;
  5339.  
  5340.         /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
  5341.         /* client and then server finished messages. */
  5342.  
  5343.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  5344.             type_check[1] = how;        /* not broken into parts */
  5345. #ifdef CK_SSL
  5346.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5347.                 ssl_get_client_finished(&type_check[2],12);
  5348.                 ssl_get_server_finished(&type_check[14],12);
  5349.                 hexdump("k5_auth_is type_check",type_check,26);
  5350.             }
  5351. #endif /* CK_SSL */
  5352.  
  5353.             r = krb5_auth_con_getkey(k5_context, auth_context,
  5354.                                       &key);
  5355.             debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
  5356.             if (r) {
  5357.                 (void) ckstrncpy(errbuf, "krb5_auth_con_getkey failed: ",
  5358.                   sizeof(errbuf));
  5359.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5360.                 goto errout;
  5361.             }
  5362.  
  5363.             r = krb5_verify_checksum(k5_context,
  5364.                                       cksum->checksum_type,
  5365.                                       cksum,
  5366.                                       &type_check,
  5367.                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  5368.                                       2,
  5369.                                       key->contents,
  5370.                                       key->length
  5371.                                       );
  5372.             debug(F111,"k5_auth_is","krb5_verify_checksum",r);
  5373.             if (r) {
  5374.                 (void) ckstrncpy(errbuf,
  5375.                  "checksum verification failed: ",
  5376.                  sizeof(errbuf)
  5377.                  );
  5378.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5379.                 goto errout;
  5380.             }
  5381.             krb5_free_keyblock(k5_context, key);
  5382.         } else {
  5383.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
  5384.                 (void) strcpy(errbuf,
  5385.                                "authenticator is missing required checksum");
  5386.                 goto errout;
  5387.             }
  5388.         }
  5389.  
  5390.         krb5_free_authenticator(k5_context, authenticator);
  5391. #endif /* HEIMDAL */
  5392.  
  5393. #ifdef TLS_VERIFY
  5394.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5395.             krb5_data in, msg;
  5396.             char tls_verify[24];
  5397.             krb5_replay_data repdata;
  5398.  
  5399.             ssl_get_server_finished(&tls_verify[0],12);
  5400.             ssl_get_client_finished(&tls_verify[12],12);
  5401.  
  5402.             in.data = tls_verify;
  5403.             in.length = 24;
  5404.  
  5405.             if (!krb5_d_no_addresses)
  5406.                 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  5407.                    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
  5408.             if (r = krb5_mk_safe(k5_context,auth_context,&in,&msg,&repdata)) {
  5409.                 com_err("", r, "encoding tls verifier");
  5410.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5411.                 goto errout;
  5412.             }
  5413.             SendK5AuthSB(KRB5_TLS_VERIFY, msg.data, msg.length);
  5414.             krb5_free_data_contents(k5_context,&msg);
  5415.         }
  5416. #endif /* CK_SSL */
  5417.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  5418.             /* do ap_rep stuff here */
  5419.             if ((r = krb5_mk_rep(k5_context,
  5420. #ifdef HEIMDAL
  5421.                                   &auth_context,
  5422. #else /* HEIMDAL */
  5423.                                   auth_context,
  5424. #endif /* HEIMDAL */
  5425.                                   &outbuf))) {
  5426.                 debug(F111,"k5_auth_is","krb5_mk_rep",r);
  5427.                 (void) ckstrncpy(errbuf, "Make reply failed: ",sizeof(errbuf));
  5428.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5429.                 goto errout;
  5430.             }
  5431.             debug(F111,"k5_auth_is","krb5_mk_rep",r);
  5432.  
  5433.             SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
  5434.             mutual_complete = 1;
  5435.         }
  5436.  
  5437. #ifdef HEIMDAL
  5438.         {
  5439.             char * name = NULL;
  5440.             if (krb5_unparse_name(k5_context, k5_ticket->client,
  5441.                                    &name))
  5442.             {
  5443.                 szUserNameAuthenticated[0] = '\0';
  5444.             } else {
  5445.                 ckstrncpy(szUserNameAuthenticated,UIDBUFLEN,name);
  5446.                 free(name);
  5447.             }
  5448.         }
  5449. #else /* HEIMDAL */
  5450.         if ( krb5_aname_to_localname(k5_context,
  5451.                                       k5_ticket->enc_part2->client,
  5452.                                       UIDBUFLEN,szUserNameAuthenticated) )
  5453.             szUserNameAuthenticated[0] = '\0';
  5454. #endif /* HEIMDAL */
  5455.  
  5456.         SendK5AuthSB(KRB_ACCEPT, szUserNameAuthenticated,
  5457.                       szUserNameAuthenticated[0] ? -1 : 0);
  5458.         accept_complete = 1;
  5459.         ckmakmsg(strTmp,sizeof(strTmp),
  5460.                  "Kerberos5 identifies him as ``",
  5461.                  szUserNameAuthenticated,"''",NULL);
  5462.         printf("%s\r\n",strTmp);
  5463.  
  5464.     if (szUserNameRequested[0] &&
  5465.         krb5_kuserok(k5_context,
  5466. #ifdef HEIMDAL
  5467.                           k5_ticket->client,
  5468. #else /* HEIMDAL */
  5469.                           k5_ticket->enc_part2->client,
  5470. #endif /* HEIMDAL */
  5471.                           szUserNameRequested))
  5472.         auth_finished(AUTH_VALID);
  5473.     else
  5474.         auth_finished(AUTH_USER);
  5475.  
  5476.         krb5_auth_con_getremotesubkey(k5_context, auth_context,
  5477.                                        &newkey);
  5478.         if (k5_session_key) {
  5479.             krb5_free_keyblock(k5_context, k5_session_key);
  5480.             k5_session_key = 0;
  5481.         }
  5482.         if (newkey) {
  5483.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  5484.             krb5_free_keyblock(k5_context, newkey);
  5485.         } else {
  5486.             krb5_copy_keyblock(k5_context,
  5487. #ifdef HEIMDAL
  5488.                                 &k5_ticket->ticket.key,
  5489. #else /* HEIMDAL */
  5490.                                 k5_ticket->enc_part2->session,
  5491. #endif /* HEIMDAL */
  5492.                                 &k5_session_key);
  5493.         }
  5494.  
  5495. #ifdef CK_ENCRYPTION
  5496. #ifdef HEIMDAL
  5497.         skey.type = k5_session_key->keyvalue.length == 8 ? SK_DES : SK_GENERIC;
  5498.         skey.length = k5_session_key->keyvalue.length;
  5499.         skey.data = k5_session_key->keyvalue.data;
  5500. #else /* HEIMDAL */
  5501.         skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
  5502.         skey.length = k5_session_key->length;
  5503.         skey.data = k5_session_key->contents;
  5504. #endif /* HEIMDAL */
  5505.         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  5506. #endif /* CK_ENCRYPTION */
  5507.         debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
  5508.         krb5_errno = r;
  5509.         if ( krb5_errno )
  5510.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5511.         else
  5512.             makestr(&krb5_errmsg,strTmp);
  5513.         return AUTH_SUCCESS;
  5514.  
  5515. #ifdef FORWARD
  5516.     case KRB5_FORWARD:
  5517.     if ( !forward_flag ) {
  5518.             SendK5AuthSB(KRB5_FORWARD_REJECT,
  5519.               "forwarded credentials are being refused.",
  5520.               -1);
  5521.         return(AUTH_SUCCESS);
  5522.     }
  5523.  
  5524.         inbuf.length = cnt;
  5525.         inbuf.data = (char *)data;
  5526.         if (
  5527. #ifndef HEIMDAL
  5528.             (!krb5_d_no_addresses && 
  5529.             (r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
  5530.                   KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) ||
  5531. #endif /* HEIMDAL */
  5532.         (r = rd_and_store_for_creds(k5_context, auth_context,&inbuf,
  5533. #ifdef HEIMDAL
  5534.                                          k5_ticket->client
  5535. #else /* HEIMDAL */
  5536.                                          k5_ticket->enc_part2->client
  5537. #endif /* HEIMDAL */
  5538.                                          ))) {
  5539.             (void) ckstrncpy(errbuf, "Read forwarded creds failed: ",
  5540.                   sizeof(errbuf));
  5541.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5542.             SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
  5543.             printf("Could not read forwarded credentials\r\n");
  5544.             krb5_errno = r;
  5545.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5546.         }
  5547.         else {
  5548.             SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
  5549.             ckstrncpy(strTmp,"Forwarded credentials obtained",sizeof(strTmp));
  5550.             printf("%s\r\n",strTmp);
  5551.             krb5_errno = 0;
  5552.             makestr(&krb5_errmsg,strTmp);
  5553.         }
  5554.     /* A failure to accept forwarded credentials is not an */
  5555.     /* authentication failure.                             */
  5556.     return AUTH_SUCCESS;
  5557. #endif    /* FORWARD */
  5558.     default:
  5559.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  5560.         SendK5AuthSB(KRB_REJECT, 0, 0);
  5561.         break;
  5562.     }
  5563.     auth_finished(AUTH_REJECT);
  5564.     return AUTH_FAILURE;
  5565.  
  5566.   errout:
  5567.     SendK5AuthSB(KRB_REJECT, errbuf, -1);
  5568.     krb5_errno = r;
  5569.     makestr(&krb5_errmsg,errbuf);
  5570.     printf("%s\r\n", errbuf);
  5571.     if (auth_context) {
  5572.         krb5_auth_con_free(k5_context, auth_context);
  5573.         auth_context = 0;
  5574.     }
  5575.     auth_finished(AUTH_REJECT);
  5576.     return AUTH_FAILURE;
  5577. }
  5578.  
  5579. #ifdef FORWARD
  5580. int
  5581. #ifdef CK_ANSIC
  5582. kerberos5_forward(void)
  5583. #else
  5584. kerberos5_forward()
  5585. #endif
  5586. {
  5587.     krb5_error_code r;
  5588.     krb5_ccache ccache=NULL;
  5589.     krb5_principal client = 0;
  5590.     krb5_principal server = 0;
  5591.     krb5_data forw_creds;
  5592. #ifdef HEIMDAL
  5593.     krb5_creds      creds;
  5594. #endif /* HEIMDAL */
  5595.  
  5596.     forw_creds.data = 0;
  5597.  
  5598.     r = k5_get_ccache(k5_context,&ccache,NULL);
  5599.     if ( r ) {
  5600.         com_err(NULL, r, "Kerberos V5: could not get default ccache");
  5601.         krb5_errno = r;
  5602.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5603.         return(AUTH_FAILURE);
  5604.     }
  5605.  
  5606.     if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
  5607.         com_err(NULL, r, "Kerberos V5: could not get default principal");
  5608.         goto cleanup;
  5609.     }
  5610.  
  5611. #ifdef HEIMDAL
  5612.     memset(&creds, 0, sizeof(creds));
  5613.     creds.client = client;
  5614.  
  5615.     if (r = krb5_build_principal(k5_context,
  5616.                              &creds.server,
  5617.                              strlen(client->realm),
  5618.                               client->realm,
  5619.                               "krbtgt",
  5620.                               client->realm,
  5621.                                   NULL)) {
  5622.         com_err(NULL, r, "Kerberos V5: could not get principal");
  5623.         goto cleanup;
  5624.     }
  5625.  
  5626.     creds.times.endtime = 0;
  5627.  
  5628.     if (r = krb5_get_forwarded_creds(k5_context,
  5629.                                       auth_context,
  5630.                                       ccache,
  5631.                                       0,
  5632.                                       szHostName,
  5633.                                       &creds,
  5634.                                       &forw_creds)) {
  5635.         com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
  5636.         goto cleanup;
  5637.     }
  5638. #else /* HEIMDAL */
  5639.     /* we should not need to make this call since we are storing the */
  5640.     /* server's principal in fwd_server from our call to             */
  5641.     /* krb5_sname_to_principal() in k5_auth_send()                   */
  5642.     if (fwd_server == NULL) {
  5643.         if ((r = krb5_sname_to_principal(k5_context, szHostName,
  5644.                                  krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5645.                                           KRB5_NT_SRV_HST, &server))) {
  5646.             com_err(NULL, r, "Kerberos V5: could not make server principal");
  5647.             goto cleanup;
  5648.         }
  5649.     }
  5650.  
  5651.     if (!krb5_d_no_addresses &&
  5652.         (r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
  5653.                              KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
  5654.     {
  5655.         com_err(NULL, r, "Kerberos V5: could not gen local full address");
  5656.         goto cleanup;
  5657.     }
  5658.  
  5659.     if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client,
  5660.                                 fwd_server ? fwd_server : server,
  5661.                     ccache, forwardable_flag, &forw_creds)) {
  5662.         com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
  5663.         goto cleanup;
  5664.     }
  5665. #endif /* HEIMDAL */
  5666.  
  5667.     /* Send forwarded credentials */
  5668.     if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
  5669.         printf("Kerberos V5 forwarding error!\r\n%s\r\n",
  5670.                     "Not enough room for authentication data");
  5671.     }
  5672.  
  5673. cleanup:
  5674.     if (client)
  5675.         krb5_free_principal(k5_context, client);
  5676.     if (server)
  5677.         krb5_free_principal(k5_context, server);
  5678. #ifdef HEIMDAL
  5679.     krb5_data_free(&forw_creds);
  5680. #else /* HEIMDAL */
  5681.     krb5_free_data_contents(k5_context,&forw_creds);
  5682. #endif /* HEIMDAL */
  5683.     krb5_cc_close(k5_context, ccache);
  5684.  
  5685.     krb5_errno = r;
  5686.     makestr(&krb5_errmsg,krb5_errno?error_message(krb5_errno):"OK");
  5687.     return(r?AUTH_FAILURE:AUTH_SUCCESS);
  5688. }
  5689. #endif /* FORWARD */
  5690. #else /* KRB5 */
  5691. int
  5692. ck_krb5_autoget_TGT(char * dummy)
  5693. {
  5694.     return(0);
  5695. }
  5696. #ifdef CK_KERBEROS
  5697. int
  5698. #ifdef CK_ANSIC
  5699. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
  5700.                  struct krb4_init_data * k4_init)
  5701. #else
  5702. ck_krb5_initTGT(op,init,k4_init)
  5703.     krb_op_data * op; struct krb5_init_data * init;
  5704.     struct krb4_init_data * k4_init;
  5705. #endif /* CK_ANSIC*/
  5706. {
  5707.     return(-1);
  5708. }
  5709.  
  5710. int
  5711. #ifdef CK_ANSIC
  5712. ck_krb5_destroy(struct krb_op_data * op)
  5713. #else
  5714. ck_krb5_destroy(op) struct krb_op_data * op;
  5715. #endif
  5716. {
  5717.     return(-1);
  5718. }
  5719.  
  5720. int
  5721. #ifdef CK_ANSIC
  5722. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  5723. #else
  5724. ck_krb5_list_creds(op,lc)
  5725.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  5726. #endif
  5727. {
  5728.     return(-1);
  5729. }
  5730. #else /* CK_KERBEROS */
  5731. int
  5732. #ifdef CK_ANSIC
  5733. ck_krb5_initTGT(void * op, void * init, void * k4_init )
  5734. #else
  5735. ck_krb5_initTGT(op,init,k4_init)
  5736.     void * op; void * init; void * k4_init;
  5737. #endif /* CK_ANSIC*/
  5738. {
  5739.     return(-1);
  5740. }
  5741.  
  5742. int
  5743. #ifdef CK_ANSIC
  5744. ck_krb5_destroy(void * op)
  5745. #else
  5746. ck_krb5_destroy(op) void * op;
  5747. #endif
  5748. {
  5749.     return(-1);
  5750. }
  5751.  
  5752. int
  5753. #ifdef CK_ANSIC
  5754. ck_krb5_list_creds(void * op, void * lc)
  5755. #else
  5756. ck_krb5_list_creds(op,lc)
  5757.     void * op; void * lc;
  5758. #endif
  5759. {
  5760.     return(-1);
  5761. }
  5762. #endif /* CK_KERBEROS */
  5763. #endif /* KRB5 */
  5764.  
  5765. #ifdef GSSAPI_KRB5
  5766. /*
  5767.  *
  5768.  * gssk5_auth_send - gets authentication bits we need to send to KDC.
  5769.  *
  5770.  * Result is left in k5_auth
  5771.  *
  5772.  * Returns: 0 on failure, 1 on success
  5773.  *
  5774.  */
  5775.  
  5776. static int
  5777. #ifdef CK_ANSIC
  5778. gssk5_auth_send(int how, int encrypt, int forward)
  5779. #else
  5780. gssk5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
  5781. #endif
  5782. {
  5783.     OM_uint32 maj_stat, min_stat;
  5784. #ifdef KRB5
  5785.     char * realm = NULL;
  5786.     char tgt[256];
  5787. #endif /* KRB5 */
  5788.  
  5789.     gss_chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */
  5790.     gss_chan.initiator_address.length = 4;
  5791.     gss_chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
  5792.     gss_chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
  5793.     gss_chan.acceptor_address.length = 4;
  5794.     gss_chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
  5795.     gss_chan.application_data.length = 0;
  5796.     gss_chan.application_data.value = 0;
  5797.  
  5798. #ifdef KRB5
  5799.     realm = ck_krb5_realmofhost(ftp_host);
  5800.     if (realm) {
  5801.         ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  5802.         debug(F110,"ftp_auth(GSSAPI) TGT",tgt,0);
  5803.         if ( krb5_autoget &&
  5804.              !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  5805.                 (ck_krb5_is_tgt_valid() > 0)) )
  5806.             ck_krb5_autoget_TGT(realm);
  5807.     }
  5808. #endif /* KRB5 */
  5809.  
  5810.     /* Blob from gss-client */
  5811.     /* host@hostname */
  5812.     /* the V5 GSSAPI binding canonicalizes this for us... */
  5813.     ckmakmsg(gss_stbuf,GSS_BUFSIZ,
  5814.              krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5815.              "@",
  5816.              szHostName,
  5817.               NULL
  5818.               );
  5819.     fprintf(stderr, "Authenticating to <%s>...\n", gss_stbuf);
  5820.     gss_send_tok.value = gss_stbuf;
  5821.     gss_send_tok.length = strlen(gss_stbuf);
  5822.     maj_stat = gss_import_name(&min_stat, &gss_send_tok,
  5823.                                 gss_nt_service_name,
  5824.                                 &gss_target_name
  5825.                                 );
  5826.     if (maj_stat != GSS_S_COMPLETE) {
  5827.         user_gss_error(maj_stat, min_stat, "parsing name");
  5828.         secure_error("name parsed <%s>\n", gss_stbuf);
  5829.         return(0);
  5830.     }
  5831.     token_ptr = GSS_C_NO_BUFFER;
  5832.     gcontext = GSS_C_NO_CONTEXT; /* structure copy */
  5833.  
  5834.     fprintf(stderr, "calling gss_init_sec_context\n");
  5835.     maj_stat =
  5836.         gss_init_sec_context(&min_stat,
  5837.                               GSS_C_NO_CREDENTIAL,
  5838.                               &gcontext,
  5839.                               gss_target_name,
  5840.                               gss_mech_krb5,
  5841.                               GSS_C_MUTUAL_FLAG |
  5842.                               GSS_C_REPLAY_FLAG |
  5843.                               ((forward && forward_flag) ?
  5844.                                 GSS_C_DELEG_FLAG : 0),
  5845.                               0,
  5846.                               (krb5_d_no_addresses ? /* channel bindings */
  5847.                                 GSS_C_NO_CHANNEL_BINDINGS :
  5848.                                 &gss_chan),
  5849.                               gss_token_ptr,
  5850.                               NULL,    /* ignore mech type */
  5851.                               &gss_send_tok,
  5852.                               NULL,    /* ignore ret_flags */
  5853.                               NULL
  5854.                               );    /* ignore time_rec */
  5855.  
  5856.  
  5857.         if (maj_stat != GSS_S_COMPLETE &&
  5858.              maj_stat != GSS_S_CONTINUE_NEEDED) {
  5859.             user_gss_error(maj_stat,
  5860.                             min_stat,
  5861.                             "initializing context"
  5862.                             );
  5863.             gss_release_name(&min_stat, &gss_target_name);
  5864.             return(0);
  5865.         }
  5866.         return(1);
  5867. }
  5868.  
  5869. /*
  5870.  * gssk5_auth_reply -- checks the reply for mutual authentication.
  5871.  */
  5872. static int
  5873. #ifdef CK_ANSIC
  5874. gssk5_auth_reply(int how, unsigned char *data, int cnt)
  5875. #else
  5876. gssk5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  5877. #endif
  5878. {
  5879.     data += 4;                                  /* Point to status byte */
  5880.     cnt -=5;
  5881.  
  5882.     switch (*data++) {
  5883.     case GSS_REJECT:
  5884.         if (cnt > 0) {
  5885.             char *s;
  5886.             int len;
  5887.             ckstrncpy(strTmp,"GSSAPI refuses authentication because\r\n",
  5888.                       sizeof(strTmp));
  5889.             len = strlen(strTmp);
  5890.             if ( len + cnt < sizeof(strTmp) ) {
  5891.                 s = strTmp + strlen(strTmp);
  5892.                 memcpy(s, data, cnt);           /* safe */
  5893.                 s[cnt] = 0;
  5894.             }
  5895.         } else
  5896.             ckstrncpy(strTmp,"GSSAPI refuses authentication",
  5897.                       sizeof(strTmp));
  5898.         printf("GSSAPI authentication failed!\r\n%s\r\n",strTmp);
  5899.         auth_finished(AUTH_REJECT);
  5900.         return AUTH_FAILURE;
  5901.  
  5902.     case GSS_ACCEPT:
  5903.         if ( cnt > 0 ) {
  5904.             char *s;
  5905.             int len;
  5906.             ckstrncpy(strTmp,"GSSAPI accepts you as ",sizeof(strTmp));
  5907.             len = strlen(strTmp);
  5908.             if ( len + cnt < sizeof(strTmp) ) {
  5909.                 s = strTmp + strlen(strTmp);
  5910.                 memcpy(s,data,cnt);
  5911.                 s[cnt] = 0;
  5912.             }
  5913.         }
  5914.         accept_complete = 1;
  5915.         printf("%s\r\n",strTmp);
  5916.         auth_finished(AUTH_USER);
  5917.         return AUTH_SUCCESS;
  5918.  
  5919.     case GSS_RESPONSE:
  5920.         gss_token_ptr = &gss_recv_tok;
  5921.         gss_recv_tok.value = data;
  5922.         gss_recv_tok.length = cnt;
  5923.  
  5924.         maj_stat =
  5925.             gss_init_sec_context(&min_stat,
  5926.                                   GSS_C_NO_CREDENTIAL,
  5927.                                   &gcontext,
  5928.                                   gss_target_name,
  5929.                                   gss_krb5_mech,
  5930.                                   GSS_C_MUTUAL_FLAG |
  5931.                                   GSS_C_REPLAY_FLAG |
  5932.                                   (forward_flag ?
  5933.                                     GSS_C_DELEG_FLAG : 0),
  5934.                                   0,
  5935.                                   (krb5_d_no_addresses ? /* channel bindings */
  5936.                                     GSS_C_NO_CHANNEL_BINDINGS :
  5937.                                     &gss_chan),
  5938.                                   gss_token_ptr,
  5939.                                   NULL,    /* ignore mech type */
  5940.                                   &gss_send_tok,
  5941.                                   NULL,    /* ignore ret_flags */
  5942.                                   NULL
  5943.                                   );    /* ignore time_rec */
  5944.  
  5945.         if ( maj_stat == GSS_S_COMPLETE )
  5946.         {
  5947.  
  5948.         } else if ( maj_stat == CSS_S_CONTINUE_NEEDED ) {
  5949.         } else {
  5950.         }
  5951.  
  5952.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  5953.                   sizeof(strTmp));
  5954.         printf("%s\r\n",strTmp);
  5955.         auth_finished(AUTH_USER);
  5956.         return AUTH_SUCCESS;
  5957.  
  5958.     default:
  5959.         auth_finished(AUTH_REJECT);
  5960.         return AUTH_FAILURE;                        /* Unknown reply type */
  5961.     }
  5962. }
  5963.  
  5964. /*
  5965.  *
  5966.  * gssk5_auth_is.
  5967.  *
  5968.  */
  5969.  
  5970. static int
  5971. #ifdef CK_ANSIC
  5972. k5_auth_is(int how, unsigned char *data, int cnt)
  5973. #else
  5974. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  5975. #endif
  5976. {
  5977.     int replied = 0;
  5978.     gss_cred_id_t server_creds, deleg_creds;
  5979.     gss_name_t client;
  5980.     int ret_flags;
  5981.     gss_buffer_desc name_buf;
  5982.     gss_name_t server_name;
  5983.     OM_uint32 acquire_maj,
  5984.       acquire_min,
  5985.       accept_maj,
  5986.       accept_min,
  5987.       stat_maj,
  5988.       stat_min;
  5989.     gss_OID mechid;
  5990.     gss_buffer_desc tok, out_tok;
  5991.     char gbuf[GSS_BUFSIZ];
  5992.     u_char gout_buf[GSS_BUFSIZ];
  5993.     char localname[MAXHOSTNAMELEN];
  5994.     char service_name[MAXHOSTNAMELEN+10];
  5995.     char **service;
  5996.     struct hostent *hp;
  5997.  
  5998.     data += 4;                                  /* Point to status byte */
  5999.     cnt -= 4;
  6000.  
  6001.     hexdump("gssk5_auth_is data",data,cnt);
  6002.     debug(F111,"gssk5_auth_is","how",how);
  6003.  
  6004.     if (cnt-- < 1) {
  6005.         auth_finished(AUTH_REJECT);
  6006.         return AUTH_FAILURE;
  6007.     }
  6008.     switch (*data++) {
  6009.     case GSS_AUTH:
  6010.         gss_chan.initiator_addrtype = GSS_C_AF_INET;
  6011.         gss_chan.initiator_address.length = 4;
  6012.         gss_chan.initiator_address.value = &his_addr.sin_addr.s_addr;
  6013.         gss_chan.acceptor_addrtype = GSS_C_AF_INET;
  6014.         gss_chan.acceptor_address.length = 4;
  6015.         gss_chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
  6016.         gss_chan.application_data.length = 0;
  6017.         gss_chan.application_data.value = 0;
  6018.  
  6019.         tok.value = data;
  6020.         tok.length = cnt;
  6021.  
  6022.         if (gethostname(localname, MAXHOSTNAMELEN)) {
  6023.             auth_finished(AUTH_REJECT);
  6024.             return AUTH_FAILURE;
  6025.         }
  6026.         if (!(hp = gethostbyname(localname))) {
  6027.             auth_finished(AUTH_REJECT);
  6028.             return AUTH_FAILURE;
  6029.         }
  6030. #ifdef HADDRLIST
  6031.         hp = ck_copyhostent(hp);
  6032. #endif /* HADDRLIST */
  6033.         strncpy(localname, hp->h_name, sizeof(localname) - 1);
  6034.         localname[sizeof(localname) - 1] = '\0';
  6035.  
  6036.         sprintf(service_name, "%s@%s", *service, localname);
  6037.         name_buf.value = service_name;
  6038.         name_buf.length = strlen(name_buf.value) + 1;
  6039.         stat_maj = gss_import_name(&stat_min, &name_buf,
  6040.                                     gss_nt_service_name,
  6041.                                     &server_name);
  6042.         if (stat_maj != GSS_S_COMPLETE) {
  6043.             auth_finished(AUTH_REJECT);
  6044.             return AUTH_FAILURE;
  6045.         }
  6046.  
  6047.         acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
  6048.                                         GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
  6049.                                         &server_creds, NULL, NULL);
  6050.         (void) gss_release_name(&stat_min, &server_name);
  6051.  
  6052.         if (acquire_maj != GSS_S_COMPLETE) {
  6053.             reply_gss_error(535, accept_maj, accept_min,
  6054.                                  "accepting context");
  6055.             syslog(LOG_ERR, "failed accepting context");
  6056.             (void) gss_release_cred(&stat_min, &server_creds);
  6057.             if (ret_flags & GSS_C_DELEG_FLAG)
  6058.                 (void) gss_release_cred(&stat_min,
  6059.                                          &deleg_creds);
  6060.             return 0;
  6061.         }
  6062.  
  6063.         gcontext = GSS_C_NO_CONTEXT;
  6064.         accept_maj = gss_accept_sec_context(&accept_min,
  6065.                         &gcontext, /* context_handle */
  6066.                         /* verifier_cred_handle */
  6067.                         server_creds,
  6068.                         &tok, /* input_token */
  6069.                                              (krb5_d_no_addresses ? /* channel bindings */
  6070.                                                GSS_C_NO_CHANNEL_BINDINGS :
  6071.                                                &gss_chan),
  6072.                                              &client, /* src_name */
  6073.                         &mechid, /* mech_type */
  6074.                         &out_tok, /* output_token */
  6075.                         &ret_flags,
  6076.                         NULL,       /* ignore time_rec */
  6077.                         /* forwarded credentials */
  6078.                         &deleg_creds
  6079.                         );
  6080.  
  6081.         if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
  6082.             reply_gss_error(535, accept_maj, accept_min,
  6083.                              "accepting context");
  6084.             syslog(LOG_ERR, "failed accepting context");
  6085.             (void) gss_release_cred(&stat_min, &server_creds);
  6086.             if (ret_flags & GSS_C_DELEG_FLAG)
  6087.                 (void) gss_release_cred(&stat_min,
  6088.                                          &deleg_creds);
  6089.             return 0;
  6090.         }
  6091.  
  6092.         if (out_tok.length) {
  6093.             if (kerror = radix_encode(out_tok.value,gbuf,&out_tok.length, 0)) {
  6094.                 secure_error("Couldn't encode ADAT reply (%s)",
  6095.                              radix_error(kerror));
  6096.                 syslog(LOG_ERR, "couldn't encode ADAT reply");
  6097.                 (void) gss_release_cred(&stat_min, &server_creds);
  6098.                 if (ret_flags & GSS_C_DELEG_FLAG)
  6099.                         (void) gss_release_cred(&stat_min,
  6100.                                                 &deleg_creds);
  6101.                 return(0);
  6102.             }
  6103.             if (stat_maj == GSS_S_COMPLETE) {
  6104.                 reply(235, "ADAT=%s", gbuf);
  6105.                 replied = 1;
  6106.             } else {
  6107.                 /* If the server accepts the security data, and
  6108.                    requires additional data, it should respond
  6109.                    with reply code 335. */
  6110.                 reply(335, "ADAT=%s", gbuf);
  6111.             }
  6112.             (void) gss_release_buffer(&stat_min, &out_tok);
  6113.         }
  6114.  
  6115.         if (stat_maj == GSS_S_COMPLETE) {
  6116.             /* GSSAPI authentication succeeded */
  6117.             stat_maj = gss_display_name(&stat_min, client,
  6118.                                          &client_name, &mechid);
  6119.             if (stat_maj != GSS_S_COMPLETE) {
  6120.                 /* "If the server rejects the security data (if
  6121.                    a checksum fails, for instance), it should
  6122.                    respond with reply code 535." */
  6123.                 reply_gss_error(535, stat_maj, stat_min,
  6124.                                 "extracting GSSAPI identity name");
  6125.                 syslog(LOG_ERR, "gssapi error extracting identity");
  6126.                 (void) gss_release_cred(&stat_min, &server_creds);
  6127.                 if (ret_flags & GSS_C_DELEG_FLAG)
  6128.                         (void) gss_release_cred(&stat_min,
  6129.                                                 &deleg_creds);
  6130.                 return 0;
  6131.             }
  6132.             auth_type = temp_auth_type;
  6133.             temp_auth_type = NULL;
  6134.  
  6135.             (void) gss_release_cred(&stat_min, &server_creds);
  6136.             if (ret_flags & GSS_C_DELEG_FLAG) {
  6137.                 if (want_creds)
  6138.                     ftpd_gss_convert_creds(client_name.value,
  6139.                                             deleg_creds);
  6140.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6141.             }
  6142.  
  6143.             /* If the server accepts the security data, but does
  6144.                not require any additional data (i.e., the security
  6145.                data exchange has completed successfully), it must
  6146.                respond with reply code 235. */
  6147.             if (!replied)
  6148.             {
  6149.                 if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
  6150.           reply(235,
  6151.  "GSSAPI Authentication succeeded, but could not accept forwarded credentials"
  6152.             );
  6153.                 else
  6154.           reply(235, "GSSAPI Authentication succeeded");
  6155.             }
  6156.             return(1);
  6157.         } else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
  6158.             /* If the server accepts the security data, and
  6159.             requires additional data, it should respond with
  6160.             reply code 335. */
  6161.             reply(335, "more data needed");
  6162.             (void) gss_release_cred(&stat_min, &server_creds);
  6163.             if (ret_flags & GSS_C_DELEG_FLAG)
  6164.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6165.             return(0);
  6166.         } else {
  6167.             /* "If the server rejects the security data (if
  6168.             a checksum fails, for instance), it should
  6169.             respond with reply code 535." */
  6170.             reply_gss_error(535, stat_maj, stat_min,
  6171.                              "GSSAPI failed processing ADAT");
  6172.             syslog(LOG_ERR, "GSSAPI failed processing ADAT");
  6173.             (void) gss_release_cred(&stat_min, &server_creds);
  6174.             if (ret_flags & GSS_C_DELEG_FLAG)
  6175.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6176.             return(0);
  6177.         }
  6178.  
  6179.         debug(F100,"gssk5_auth_is AUTH_SUCCESS","",0);
  6180.         krb5_errno = r;
  6181.         if ( krb5_errno )
  6182.             makestr(&krb5_errmsg,error_message(krb5_errno));
  6183.         else
  6184.             makestr(&krb5_errmsg,strTmp);
  6185.         return AUTH_SUCCESS;
  6186.  
  6187.     default:
  6188.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  6189.         SendGSSK5AuthSB(GSS_REJECT, 0, 0);
  6190.         break;
  6191.     }
  6192.     auth_finished(AUTH_REJECT);
  6193.     return AUTH_FAILURE;
  6194. }
  6195. #endif /* GSSAPI_KRB5 */
  6196.  
  6197. #ifdef CK_SRP
  6198. /*
  6199.  * Copyright (c) 1997 Stanford University
  6200.  *
  6201.  * The use of this software for revenue-generating purposes may require a
  6202.  * license from the owners of the underlying intellectual property.
  6203.  * Specifically, the SRP-3 protocol may not be used for revenue-generating
  6204.  * purposes without a license.
  6205.  *
  6206.  * NOTE: Columbia University has a license.
  6207.  *
  6208.  * Within that constraint, permission to use, copy, modify, and distribute
  6209.  * this software and its documentation for any purpose is hereby granted
  6210.  * without fee, provided that the above copyright notices and this permission
  6211.  * notice appear in all copies of the software and related documentation.
  6212.  *
  6213.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  6214.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  6215.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  6216.  *
  6217.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  6218.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  6219.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
  6220.  * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
  6221.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  6222.  */
  6223.  
  6224. static void
  6225. srp_encode_length(data, num)
  6226.     unsigned char * data;
  6227.     int num;
  6228. {
  6229.     *data = (num >> 8) & 0xff;
  6230.     *++data = num & 0xff;
  6231. }
  6232.  
  6233. static int
  6234. srp_decode_length(data)
  6235.     unsigned char * data;
  6236. {
  6237.     return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
  6238. }
  6239.  
  6240. #ifdef PRE_SRP_1_7_3 
  6241. static int
  6242. #ifdef CK_ANSIC
  6243. srp_reply(int how, unsigned char *data, int cnt)
  6244. #else
  6245. srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  6246. #endif
  6247. {
  6248.     struct t_num n;
  6249.     struct t_num g;
  6250.     struct t_num s;
  6251.     struct t_num B;
  6252.     struct t_num * A;
  6253.     char hexbuf[MAXHEXPARAMLEN];
  6254.     char type_check[26];
  6255.     int pflag;
  6256.  
  6257. #ifdef CK_ENCRYPTION
  6258.     Session_Key skey;
  6259. #endif /* ENCRYPTION */
  6260.  
  6261.     char * str=NULL;
  6262.  
  6263.     data += 4;                          /* Point to status byte */
  6264.     cnt  -= 4;
  6265.  
  6266.     if(cnt-- < 1) {
  6267.         auth_finished(AUTH_REJECT);
  6268.         return AUTH_FAILURE;
  6269.     }
  6270.  
  6271.     switch(*data++) {
  6272.     case SRP_REJECT:
  6273.         ckmakmsg(strTmp,sizeof(strTmp),
  6274.                   "SRP refuses authentication for '",szUserName,
  6275.                   "'\r\n",NULL);
  6276.         if (cnt > 0) {
  6277.             int len = strlen(strTmp);
  6278.             if ( len + cnt < sizeof(strTmp) ) {
  6279.                 str = strTmp + strlen(strTmp);
  6280.                 memcpy(str,data,cnt);
  6281.                 str[cnt] = 0;
  6282.             }
  6283.         }
  6284.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  6285.         if (tc != NULL) {
  6286.             t_clientclose(tc);
  6287.             tc = NULL;
  6288.         }
  6289.         auth_finished(AUTH_REJECT);
  6290.         return AUTH_FAILURE;
  6291.  
  6292.     case SRP_ACCEPT:
  6293.         if(cnt < RESPONSE_LEN || !srp_waitresp || 
  6294.             tc == NULL
  6295.             ) {
  6296.             printf("SRP Protocol error\r\n");
  6297.             return(auth_resend(AUTHTYPE_SRP));
  6298.         }
  6299.         srp_waitresp = 0;
  6300.  
  6301.         if(t_clientverify(tc, data) == 0) {
  6302.             printf("SRP accepts you as %s\r\n",szUserName);
  6303. #ifdef CK_SSL
  6304.             if((ssl_active_flag || tls_active_flag) &&
  6305.                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6306.                 printf("TLS session parameters verified by SRP\r\n");
  6307.             } else
  6308. #endif /* CK_SSL */
  6309.  
  6310. #ifdef CK_ENCRYPTION
  6311.             {
  6312.                 skey.type = SK_GENERIC;
  6313.                 skey.length = SESSION_KEY_LEN;
  6314.                 skey.data = tc->session_key;
  6315.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  6316.             }
  6317. #endif /* ENCRYPTION */
  6318.             t_clientclose(tc);
  6319.             tc = NULL;
  6320.             accept_complete = 1;
  6321.             auth_finished(AUTH_VALID);
  6322.             return AUTH_SUCCESS;
  6323.         } else {
  6324.             printf("SRP server authentication failed!\r\n");
  6325.             t_clientclose(tc);
  6326.             tc = NULL;
  6327.             return(auth_resend(AUTHTYPE_SRP));
  6328.         }
  6329.         break;
  6330.  
  6331.     case SRP_PARAMS:
  6332.         if(!szUserName) {
  6333.             printf("No username available\r\n");
  6334.             return(auth_resend(AUTHTYPE_SRP));
  6335.         }
  6336.  
  6337.         n.len = srp_decode_length(data);
  6338.         data += 2;
  6339.         cnt -= 2;
  6340.         if(n.len > cnt) {
  6341.             printf("n too long\r\n");
  6342.             return(auth_resend(AUTHTYPE_SRP));
  6343.         }
  6344.         n.data = data;
  6345.         data += n.len;
  6346.         cnt -= n.len;
  6347.  
  6348.         g.len = srp_decode_length(data);
  6349.         data += 2;
  6350.         cnt -= 2;
  6351.         if(g.len > cnt) {
  6352.             printf("g too long\r\n");
  6353.             return(auth_resend(AUTHTYPE_SRP));
  6354.         }
  6355.         g.data = data;
  6356.         data += g.len;
  6357.         cnt -= g.len;
  6358.  
  6359.         s.len = srp_decode_length(data);
  6360.         data += 2;
  6361.         cnt -= 2;
  6362.         if(s.len > cnt) {
  6363.             printf("salt too long\r\n");
  6364.             return(auth_resend(AUTHTYPE_SRP));
  6365.         }
  6366.         s.data = data;
  6367.         data += s.len;
  6368.         cnt -= s.len;
  6369.  
  6370.         /* If the parameters provided by the server cannot be
  6371.          * validated the following function will fail.
  6372.          */
  6373.         tc = t_clientopen(szUserName, &n, &g, &s);
  6374.         if (tc == NULL) {
  6375.             printf("SRP parameter initialization error\r\n");
  6376.             return(auth_resend(AUTHTYPE_SRP));
  6377.         }
  6378.         A = t_clientgenexp(tc);
  6379.         if(A == NULL) {
  6380.             printf("SRP protocol error\r\n");
  6381.             return(auth_resend(AUTHTYPE_SRP));
  6382.         }
  6383.         SendSRPAuthSB(SRP_EXP, A->data, A->len);
  6384.  
  6385.         if ( pwbuf[0] && pwflg ) {
  6386.             printf("SRP using %d-bit modulus for '%s'\r\n",
  6387.            8 * n.len,
  6388.            szUserName
  6389.            );
  6390.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  6391. #ifdef OS2
  6392.             if ( pwcrypt )
  6393.                 ck_encrypt((char *)srp_passwd);
  6394. #endif /* OS2 */
  6395.         } else {
  6396.             extern char * srppwprompt;
  6397.             char prompt[128];
  6398.  
  6399.             if (srppwprompt && srppwprompt[0] &&
  6400.                (strlen(srppwprompt) + strlen(szUserName) - 2) < sizeof(prompt))
  6401.             {
  6402.                 sprintf(prompt,srppwprompt,szUserName);
  6403.             } else {
  6404.                 ckmakxmsg( prompt,sizeof(prompt),
  6405.                            "SRP using ",ckitoa(8*n.len),"-bit modulus\r\n",
  6406.                            szUserName,"'s password: ",
  6407.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6408.             }
  6409.             readpass(prompt,srp_passwd,sizeof(srp_passwd)-1);
  6410.         }
  6411.  
  6412.         t_clientpasswd(tc, srp_passwd);
  6413.         memset(srp_passwd, 0, sizeof(srp_passwd));
  6414.         return AUTH_SUCCESS;
  6415.  
  6416.     case SRP_CHALLENGE:
  6417.         if(tc == NULL) {
  6418.             printf("SRP protocol error\r\n");
  6419.             return(auth_resend(AUTHTYPE_SRP));
  6420.         }
  6421.  
  6422. #ifndef PRE_SRP_1_4_5
  6423.         /*
  6424.          * The original SRP AUTH implementation did not protect against
  6425.          * tampering of the auth-type-pairs.  Therefore, when the
  6426.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6427.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6428.          * is set we also insert the SSL/TLS client and server finished
  6429.          * messages to ensure that there is no man in the middle attack
  6430.          * underway on the SSL/TLS connection.
  6431.          */
  6432.         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
  6433.             type_check[0] = AUTHTYPE_SRP;
  6434.             type_check[1] = how;
  6435. #ifdef CK_SSL
  6436.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6437.                 ssl_get_client_finished(&type_check[2],12);
  6438.                 ssl_get_server_finished(&type_check[14],12);
  6439.                 t_clientaddexdata(tc,type_check,26);
  6440.             } else
  6441. #endif /* CK_SSL */
  6442.                 t_clientaddexdata(tc,type_check,2);
  6443.         }
  6444. #endif /* PRE_SRP_1_4_5 */
  6445.  
  6446.         B.data = data;
  6447.         B.len = cnt;
  6448.         t_clientgetkey(tc, &B);
  6449.  
  6450.         SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
  6451.         srp_waitresp = 1;
  6452.         return AUTH_SUCCESS;
  6453.  
  6454.     default:
  6455.         return(auth_resend(AUTHTYPE_SRP));
  6456.     }
  6457.     return AUTH_FAILURE;
  6458. }
  6459.  
  6460. static int
  6461. #ifdef CK_ANSIC
  6462. srp_is(int how, unsigned char *data, int cnt)
  6463. #else
  6464. srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  6465. #endif
  6466. {
  6467.     char pbuf[2 * MAXPARAMLEN + 5];
  6468.     char * ptr;
  6469.     char hexbuf[MAXHEXPARAMLEN];
  6470. #ifdef CK_ENCRYPTION
  6471.     Session_Key skey;
  6472. #endif
  6473.     struct t_num A;
  6474.     struct t_pw * tpw = NULL;
  6475.     struct t_conf * tconf = NULL;
  6476.     struct passwd * pass;
  6477.     static struct t_num * B = NULL;    /* Holder for B */
  6478. #ifdef CK_SSL
  6479.     char type_check[26];
  6480. #else
  6481.     char type_check[2];
  6482. #endif /* CK_SSL */
  6483.  
  6484.     if ((cnt -= 4) < 1) {
  6485.         auth_finished(AUTH_REJECT);
  6486.         return AUTH_FAILURE;
  6487.     }
  6488.  
  6489.     data += 4;
  6490.     cnt  -= 1;
  6491.     switch(*data++) {
  6492.     case SRP_AUTH:
  6493.         /* Send parameters back to client */
  6494.         if(ts != NULL) {
  6495.             t_serverclose(ts);
  6496.             ts = NULL;
  6497.         }
  6498.         if(!szUserNameRequested[0]) {
  6499.             if (1)
  6500.                 printf("No username available\r\n");
  6501.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  6502.             auth_finished(AUTH_REJECT);
  6503.             return(AUTH_FAILURE);
  6504.         }
  6505. #ifdef IKSD
  6506. #ifdef CK_LOGIN
  6507.         if (inserver && ckxanon &&
  6508.              !strcmp(szUserNameRequested,"anonymous")) {
  6509.             SendSRPAuthSB(SRP_REJECT, (void *)
  6510.             "anonymous login cannot be performed with Secure Remote Password",
  6511.             -1);
  6512.             auth_finished(AUTH_REJECT);
  6513.             return(AUTH_FAILURE);
  6514.         }
  6515. #endif /* CK_LOGIN */
  6516. #endif /* IKSD */
  6517. #ifndef PRE_SRP_1_4_4
  6518.         if(tpw == NULL) {
  6519.             if((tpw = t_openpw(NULL)) == NULL) {
  6520.                 if (1)
  6521.                     printf("Unable to open password file\r\n");
  6522.                 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
  6523.                 return(AUTH_FAILURE);
  6524.             }
  6525.         }
  6526.         if(tconf == NULL) {
  6527.             if((tconf = t_openconf(NULL)) == NULL) {
  6528.                 if (1)
  6529.           printf("Unable to open configuration file\r\n");
  6530.                 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
  6531.                 return(AUTH_FAILURE);
  6532.             }
  6533.         }
  6534.         ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  6535.         t_closepw(tpw);
  6536.         tpw = NULL;
  6537.         t_closeconf(tconf);
  6538.         tconf = NULL;
  6539. #else /* PRE_SRP_1_4_4 */
  6540. #ifdef COMMENT
  6541.         /* the code in this block should no longer be necessary on OS/2
  6542.            or Windows because I have added functionality to libsrp.lib
  6543.            to find the srp files.   4/22/2000
  6544.         */
  6545.  
  6546.         /* On Windows and OS/2 there is no well defined place for the */
  6547.         /* ETC directory.  So we look for either an SRP_ETC or ETC    */
  6548.         /* environment variable in that order.  If we find one we     */
  6549.         /* attempt to open the files manually.                        */
  6550.         /* We will reuse the pbuf[] for the file names. */
  6551.         ptr = getenv("SRP_ETC");
  6552.         if ( !ptr )
  6553.             ptr = getenv("ETC");
  6554. #ifdef NT
  6555.         if ( !ptr ) {
  6556.             DWORD len;
  6557.             len = (2 * MAXPARAMLEN + 5);
  6558.  
  6559.             len = GetWindowsDirectory(pbuf,len);
  6560.             if ( len > 0 && len < (2 * MAXPARAMLEN + 5)) {
  6561.                 if ( !isWin95() ) {
  6562.                     if ( len == 1 )
  6563.                         ckstrncat(pbuf,"SYSTEM32/DRIVERS/ETC",sizeof(pbuf));
  6564.                     else
  6565.                         ckstrncat(pbuf,"/SYSTEM32/DRIVERS/ETC",sizeof(pbuf));
  6566.                 }
  6567.             }
  6568.             ptr = pbuf;
  6569.         }
  6570. #endif /* NT */
  6571.         if ( ptr ) {
  6572.             int len = strlen(ptr);
  6573.             int i;
  6574.             strcpy(pbuf,ptr);
  6575.             for ( i=0;i<len;i++ ) {
  6576.                 if ( pbuf[i] == '\\' )
  6577.                     pbuf[i] = '/';
  6578.             }
  6579.             if ( pbuf[len-1] != '/' )
  6580.                 ckstrncat(pbuf,"/tpasswd",sizeof(pbuf));
  6581.             else
  6582.                 ckstrncat(pbuf,"tpasswd",sizeof(pbuf));
  6583.             tpw = t_openpwbyname(pbuf);
  6584.  
  6585.             ckstrncat(pbuf,".conf",sizeof(pbuf));
  6586.             tconf = t_openconfbyname(pbuf);
  6587.         }
  6588.  
  6589.         if ( tpw && tconf )
  6590.             ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  6591.         else
  6592.             ts = t_serveropen(szUserNameRequested);
  6593.         if ( tpw ) {
  6594.             t_closepw(tpw);
  6595.             tpw = NULL;
  6596.         }
  6597.         if ( tconf ) {
  6598.             t_closeconf(tconf);
  6599.             tconf = NULL;
  6600.         }
  6601. #else /* COMMENT */
  6602.         ts = t_serveropen(szUserNameRequested);
  6603. #endif /* COMMENT */
  6604. #endif /* PRE_SRP_1_4_4 */
  6605.  
  6606.         if( ts == NULL ) {
  6607.             printf("User %s not found\r\n", szUserNameRequested);
  6608.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  6609.             return(AUTH_FAILURE);
  6610.         }
  6611.  
  6612.         if ( ts->n.len + ts->g.len + ts->s.len + 6 > sizeof(pbuf) ) {
  6613.             printf("message length error\r\n");
  6614.             SendSRPAuthSB(SRP_REJECT, (void *) "message length error", -1);
  6615.             return(AUTH_FAILURE);
  6616.         }
  6617.         ptr = pbuf;
  6618.  
  6619.         srp_encode_length(ptr, ts->n.len);
  6620.         ptr += 2;
  6621.         memcpy(ptr, ts->n.data, ts->n.len);     /* safe */
  6622.         ptr += ts->n.len;
  6623.  
  6624.         srp_encode_length(ptr, ts->g.len);
  6625.         ptr += 2;
  6626.         memcpy(ptr, ts->g.data, ts->g.len);     /* safe */
  6627.         ptr += ts->g.len;
  6628.  
  6629.         srp_encode_length(ptr, ts->s.len);
  6630.         ptr += 2;
  6631.         memcpy(ptr, ts->s.data, ts->s.len);     /* safe */
  6632.         ptr += ts->s.len;
  6633.  
  6634.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  6635.  
  6636.         B = t_servergenexp(ts);
  6637.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
  6638.         return AUTH_SUCCESS;
  6639.  
  6640.     case SRP_EXP:
  6641.         /* Client is sending A to us, compute challenge & expected response. */
  6642.         if (ts == NULL || B == NULL) {
  6643.             printf("Protocol error: SRP_EXP unexpected\r\n");
  6644.             SendSRPAuthSB(SRP_REJECT,
  6645.               (void *) "Protocol error: unexpected EXP",
  6646.               -1
  6647.               );
  6648.             return(AUTH_FAILURE);
  6649.         }
  6650.  
  6651.         /* Wait until now to send B, since it contains the key to "u" */
  6652.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
  6653.         B = NULL;
  6654.  
  6655. #ifndef PRE_SRP_1_4_5
  6656.         /*
  6657.          * The original SRP AUTH implementation did not protect against
  6658.          * tampering of the auth-type-pairs.  Therefore, when the
  6659.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6660.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6661.          * is set we also insert the SSL/TLS client and server finished
  6662.          * messages to ensure that there is no man in the middle attack
  6663.          * underway on the SSL/TLS connection.
  6664.          */
  6665.         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
  6666.             type_check[0] = AUTHTYPE_SRP;
  6667.             type_check[1] = how;
  6668. #ifdef CK_SSL
  6669.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6670.                 ssl_get_client_finished(&type_check[2],12);
  6671.                 ssl_get_server_finished(&type_check[14],12);
  6672.             }
  6673. #endif /* CK_SSL */
  6674.             t_serveraddexdata(ts,type_check,
  6675. #ifdef CK_SSL
  6676.                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  6677. #endif /* CK_SSL */
  6678.                                2);
  6679.         }
  6680. #endif /* PRE_SRP_1_4_5 */
  6681.  
  6682.         A.data = data;
  6683.         A.len = cnt;
  6684.         ptr = t_servergetkey(ts, &A);
  6685.  
  6686.         if(ptr == NULL) {
  6687.             if (1)
  6688.           printf("Security alert: Trivial session key attempted\r\n");
  6689.             SendSRPAuthSB(SRP_REJECT,
  6690.               (void *) "Trivial session key detected",
  6691.               -1
  6692.               );
  6693.             return(AUTH_FAILURE);
  6694.         }
  6695.         srp_waitresp = 1;
  6696.         return AUTH_SUCCESS;
  6697.  
  6698.     case SRP_RESPONSE:
  6699.         /* Got the response; see if it's correct */
  6700.         if (!srp_waitresp ||
  6701.              ts == NULL
  6702.              ) {
  6703.             if (1)
  6704.           printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  6705.             SendSRPAuthSB(SRP_REJECT,
  6706.               (void *) "Protocol error: unexpected RESPONSE",
  6707.               -1
  6708.               );
  6709.             return(AUTH_FAILURE);
  6710.         }
  6711.     srp_waitresp = 0;    /* we got a response */
  6712.  
  6713.         if (cnt < RESPONSE_LEN) {
  6714.             if (1)
  6715.           printf("Protocol error: malformed response\r\n");
  6716.             SendSRPAuthSB(SRP_REJECT,
  6717.               (void *) "Protocol error: malformed response",
  6718.               -1
  6719.               );
  6720.             return(AUTH_FAILURE);
  6721.         }
  6722.  
  6723.         if (t_serververify(ts, data) == 0) {
  6724.             SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
  6725.             accept_complete = 1;
  6726. #ifdef CK_ENCRYPTION
  6727. #ifdef CK_SSL
  6728.             if (!(ssl_active_flag || tls_active_flag)) 
  6729. #endif /* CK_SSL */
  6730.             {
  6731.                 hexdump("SRP_RESPONSE ts",ts,sizeof(ts));
  6732.                 hexdump("SRP_RESPONSE session_key",
  6733.                          ts->session_key,
  6734.                          SESSION_KEY_LEN
  6735.                          );
  6736.                 skey.type = SK_GENERIC;
  6737.                 skey.length = SESSION_KEY_LEN;
  6738.                 skey.data = ts->session_key;
  6739.                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  6740.             }
  6741. #endif /* CK_ENCRYPTION */
  6742.             auth_finished(AUTH_VALID);
  6743.         }
  6744.         else {
  6745.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  6746.             auth_finished(AUTH_REJECT);
  6747.             return(AUTH_FAILURE);
  6748.         }
  6749.         return AUTH_SUCCESS;
  6750.  
  6751.     default:
  6752.         printf("Unknown SRP option %d\r\n", data[-1]);
  6753.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  6754.         return(AUTH_FAILURE);
  6755.     }
  6756. }
  6757. #else /* PRE_SRP_1_7_3 */
  6758. static int
  6759. #ifdef CK_ANSIC
  6760. new_srp_reply(int how, unsigned char *data, int cnt)
  6761. #else
  6762. new_srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  6763. #endif
  6764. {
  6765.     data += 4;                          /* Point to status byte */
  6766.     cnt  -= 4;
  6767.  
  6768.     if(cnt-- < 1) {                     /* Matches with data++ */
  6769.         auth_finished(AUTH_REJECT);
  6770.         return AUTH_FAILURE;
  6771.     }
  6772.  
  6773.     switch(*data++) {
  6774.     case SRP_PARAMS: {
  6775.         struct t_num n;
  6776.         struct t_num g;
  6777.         struct t_num s;
  6778.         cstr * A;
  6779.  
  6780.         if(!szUserName) {
  6781.             printf("No username available\r\n");
  6782.             return(auth_resend(AUTHTYPE_SRP));
  6783.         }
  6784.  
  6785.         n.len = srp_decode_length(data);
  6786.         data += 2;
  6787.         cnt -= 2;
  6788.         if(n.len > cnt) {
  6789.             printf("n too long\r\n");
  6790.             return(auth_resend(AUTHTYPE_SRP));
  6791.         }
  6792.         n.data = data;
  6793.         data += n.len;
  6794.         cnt -= n.len;
  6795.  
  6796.         g.len = srp_decode_length(data);
  6797.         data += 2;
  6798.         cnt -= 2;
  6799.         if(g.len > cnt) {
  6800.             printf("g too long\r\n");
  6801.             return(auth_resend(AUTHTYPE_SRP));
  6802.         }
  6803.         g.data = data;
  6804.         data += g.len;
  6805.         cnt -= g.len;
  6806.  
  6807.         s.len = srp_decode_length(data);
  6808.         data += 2;
  6809.         cnt -= 2;
  6810.         if(s.len != cnt) {
  6811.             printf("invalid salt\r\n");
  6812.             return(auth_resend(AUTHTYPE_SRP));
  6813.         }
  6814.         s.data = data;
  6815.         data += s.len;
  6816.         cnt -= s.len;
  6817.  
  6818.         /* If the parameters provided by the server cannot be
  6819.          * validated the following function will fail.
  6820.          */
  6821.         c_srp = SRP_new(SRP_RFC2945_client_method());
  6822.         if(c_srp == NULL ||
  6823.             SRP_set_username(c_srp, szUserName) != SRP_SUCCESS ||
  6824.             SRP_set_params(c_srp, n.data, n.len, g.data, g.len, s.data, s.len) !=
  6825.             SRP_SUCCESS) {
  6826.             printf("SRP Parameter initialization error\r\n");
  6827.             return(auth_resend(AUTHTYPE_SRP));
  6828.         }
  6829.  
  6830.         A = cstr_new();
  6831.         if(SRP_gen_pub(c_srp, &A) != SRP_SUCCESS) {
  6832.             printf("SRP Error generating key exchange\r\n");
  6833.             return(auth_resend(AUTHTYPE_SRP));
  6834.         }
  6835.  
  6836.         SendSRPAuthSB(SRP_EXP, A->data, A->length);
  6837.         cstr_free(A);
  6838.  
  6839.         if ( pwbuf[0] && pwflg ) {
  6840.             printf("SRP using %d-bit modulus for '%s'\r\n",
  6841.            8 * n.len,
  6842.            szUserName
  6843.            );
  6844.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  6845. #ifdef OS2
  6846.             if ( pwcrypt )
  6847.                 ck_encrypt((char *)srp_passwd);
  6848. #endif /* OS2 */
  6849.         } else {
  6850.             extern char * srppwprompt;
  6851.             char prompt[128];
  6852.  
  6853.             if (srppwprompt && srppwprompt[0] &&
  6854.                (strlen(srppwprompt) + strlen(szUserName) - 2) < sizeof(prompt))
  6855.             {
  6856.                 sprintf(prompt,srppwprompt,szUserName);
  6857.             } else {
  6858.                 ckmakxmsg( prompt,sizeof(prompt),
  6859.                            "SRP using ",ckitoa(8*n.len),"-bit modulus\r\n",
  6860.                            szUserName,"'s password: ",
  6861.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6862.             }
  6863.             readpass(prompt,srp_passwd,sizeof(srp_passwd)-1);
  6864.         }
  6865.  
  6866.         if(SRP_set_auth_password(c_srp, srp_passwd) != SRP_SUCCESS) {
  6867.             memset(srp_passwd, 0, sizeof(srp_passwd));
  6868.             printf("SRP Error setting client password\r\n");
  6869.             return(auth_resend(AUTHTYPE_SRP));
  6870.         }
  6871.         memset(srp_passwd, 0, sizeof(srp_passwd));
  6872.         return AUTH_SUCCESS;
  6873.     }
  6874.     case SRP_CHALLENGE: {
  6875.         char type_check[26];
  6876.         cstr * resp = NULL;
  6877.  
  6878.         if(c_srp == NULL) {
  6879.             printf("SRP protocol error\r\n");
  6880.             return(auth_resend(AUTHTYPE_SRP));
  6881.         }
  6882.  
  6883.         /*
  6884.          * The original SRP AUTH implementation did not protect against
  6885.          * tampering of the auth-type-pairs.  Therefore, when the
  6886.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6887.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6888.          * is set we also insert the SSL/TLS client and server finished
  6889.          * messages to ensure that there is no man in the middle attack
  6890.          * underway on the SSL/TLS connection.
  6891.          */
  6892.         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
  6893.             type_check[0] = AUTHTYPE_SRP;
  6894.             type_check[1] = how;
  6895. #ifdef CK_SSL
  6896.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6897.                 ssl_get_client_finished(&type_check[2],12);
  6898.                 ssl_get_server_finished(&type_check[14],12);
  6899.                 SRP_add_ex_data(c_srp, type_check, 26);
  6900.             } else
  6901. #endif /* CK_SSL */
  6902.                 SRP_add_ex_data(c_srp, type_check, 2);
  6903.         }
  6904.  
  6905.         if(SRP_compute_key(c_srp, &c_key, data, cnt) != SRP_SUCCESS) {
  6906.             printf("SRP ERROR: unable to compute client key\r\n");
  6907.             return(auth_resend(AUTHTYPE_SRP));
  6908.         }
  6909.  
  6910.         resp = cstr_new();
  6911.         if(SRP_respond(c_srp, &resp) != SRP_SUCCESS) {
  6912.             printf("SRP ERROR: unable to compute client response\r\n");
  6913.             return(auth_resend(AUTHTYPE_SRP));
  6914.         }
  6915.         SendSRPAuthSB(SRP_RESPONSE, resp->data, resp->length);
  6916.         cstr_free(resp);
  6917.         srp_waitresp = 1;
  6918.         return AUTH_SUCCESS;
  6919.     }
  6920.     case SRP_ACCEPT: {
  6921. #ifdef CK_ENCRYPTION
  6922.         Session_Key skey;
  6923. #endif /* ENCRYPTION */
  6924.  
  6925.         if(cnt < RESPONSE_LEN || !srp_waitresp || c_srp == NULL) {
  6926.             printf("SRP Protocol error\r\n");
  6927.             return(auth_resend(AUTHTYPE_SRP));
  6928.         }
  6929.         srp_waitresp = 0;
  6930.  
  6931.         if(SRP_verify(c_srp, data, cnt) == SRP_SUCCESS) {
  6932.             printf("SRP accepts you as %s\r\n",szUserName);
  6933.  
  6934. #ifdef CK_SSL
  6935.             if((ssl_active_flag || tls_active_flag) &&
  6936.                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6937.                 printf("TLS session parameters verified by SRP\r\n");
  6938.             } else
  6939. #endif /* CK_SSL */
  6940. #ifdef CK_ENCRYPTION
  6941.             {
  6942.                 skey.type = SK_GENERIC;
  6943.                 skey.length = c_key->length;
  6944.                 skey.data = c_key->data;
  6945.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  6946.                 cstr_clear_free(c_key); 
  6947.                 c_key = NULL;
  6948.             }
  6949. #endif /* CK_ENCRYPTION */
  6950.             auth_finished(AUTH_VALID);
  6951.             SRP_free(c_srp);
  6952.             c_srp = NULL;
  6953.             return AUTH_SUCCESS;
  6954.         }
  6955.         else {
  6956.             printf("[ Error: SRP server authentication failed ]\r\n");
  6957.             return(auth_resend(AUTHTYPE_SRP));
  6958.         }
  6959.     }
  6960.     case SRP_REJECT: {
  6961.         char * str=NULL;
  6962.  
  6963.         ckmakmsg(strTmp,sizeof(strTmp),
  6964.                   "SRP refuses authentication for '",szUserName,
  6965.                   "'\r\n",NULL);
  6966.         if (cnt > 0) {
  6967.             int len = strlen(strTmp);
  6968.             if ( len + cnt < sizeof(strTmp) ) {
  6969.                 str = strTmp + strlen(strTmp);
  6970.                 memcpy(str,data,cnt);
  6971.                 str[cnt] = 0;
  6972.             }
  6973.         }
  6974.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  6975.         auth_finished(AUTH_REJECT);
  6976.         return AUTH_FAILURE;
  6977.     }
  6978.     default:
  6979.         printf("Unknown SRP option %d\r\n", data[-1]);
  6980.         return(auth_resend(AUTHTYPE_SRP));
  6981.     }
  6982.     /* NEVER REACHED */
  6983. }
  6984.  
  6985. static int
  6986. #ifdef CK_ANSIC
  6987. new_srp_is(int how, unsigned char *data, int cnt)
  6988. #else
  6989. new_srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  6990. #endif
  6991. {
  6992.     char pbuf[2 * MAXPARAMLEN + 5];
  6993.     char * ptr;
  6994. #ifdef CK_ENCRYPTION
  6995.     Session_Key skey;
  6996. #endif
  6997.     static cstr * B = NULL;        /* Holder for B */
  6998.     struct t_passwd * pass;
  6999.     cstr * resp;
  7000.     char type_check[26];
  7001.  
  7002.     if ((cnt -= 4) < 1) {
  7003.         auth_finished(AUTH_REJECT);
  7004.         return AUTH_FAILURE;
  7005.     }
  7006.  
  7007.     data += 4;
  7008.     cnt  -= 1;
  7009.     switch(*data++) {
  7010.     case SRP_AUTH:
  7011.         /* Send parameters back to client */
  7012.         if(s_srp != NULL) {
  7013.             SRP_free(s_srp);
  7014.             s_srp = NULL;
  7015.         }
  7016.         if (B != NULL) {
  7017.             cstr_free(B);
  7018.             B = NULL;
  7019.         }
  7020.         if(!szUserNameRequested[0]) {
  7021.             if (1)
  7022.                 printf("No username available\r\n");
  7023.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  7024.             auth_finished(AUTH_REJECT);
  7025.             return(AUTH_FAILURE);
  7026.         }
  7027. #ifdef IKSD
  7028. #ifdef CK_LOGIN
  7029.         if (inserver && ckxanon &&
  7030.              !strcmp(szUserNameRequested,"anonymous")) {
  7031.             SendSRPAuthSB(SRP_REJECT, (void *)
  7032.             "anonymous login cannot be performed with Secure Remote Password",
  7033.             -1);
  7034.             auth_finished(AUTH_REJECT);
  7035.             return(AUTH_FAILURE);
  7036.         }
  7037. #endif /* CK_LOGIN */
  7038. #endif /* IKSD */
  7039.         s_srp = SRP_new(SRP_RFC2945_server_method());
  7040.         if(s_srp == NULL) {
  7041.             printf("Error initializing SRP server\r\n");
  7042.             SendSRPAuthSB(SRP_REJECT,
  7043.               (void *) "SRP server init failed",
  7044.               -1
  7045.               );
  7046.             return(AUTH_FAILURE);
  7047.         }
  7048.         pass = gettpnam(szUserNameRequested);
  7049.         if(pass == NULL) {
  7050.             printf("User %s not found\r\n", szUserNameRequested);
  7051.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  7052.             return(AUTH_FAILURE);
  7053.         }
  7054.         if(SRP_set_username(s_srp, szUserNameRequested) != SRP_SUCCESS ||
  7055.             SRP_set_params(s_srp, pass->tc.modulus.data, pass->tc.modulus.len,
  7056.                             pass->tc.generator.data, pass->tc.generator.len,
  7057.                             pass->tp.salt.data, pass->tp.salt.len) != SRP_SUCCESS ||
  7058.             SRP_set_authenticator(s_srp, pass->tp.password.data,
  7059.                                    pass->tp.password.len) != SRP_SUCCESS) {
  7060.             printf("Error initializing SRP parameters\r\n");
  7061.             SendSRPAuthSB(SRP_REJECT, (void *) "SRP parameter init failed", -1);
  7062.             return(AUTH_FAILURE);
  7063.         }
  7064.  
  7065.         ptr = pbuf;
  7066.  
  7067.         srp_encode_length(ptr, pass->tc.modulus.len);
  7068.         ptr += 2;
  7069.         memcpy(ptr, pass->tc.modulus.data, pass->tc.modulus.len);
  7070.         ptr += pass->tc.modulus.len;
  7071.  
  7072.         srp_encode_length(ptr, pass->tc.generator.len);
  7073.         ptr += 2;
  7074.         memcpy(ptr, pass->tc.generator.data, pass->tc.generator.len);
  7075.         ptr += pass->tc.generator.len;
  7076.  
  7077.         srp_encode_length(ptr, pass->tp.salt.len);
  7078.         ptr += 2;
  7079.         memcpy(ptr, pass->tp.salt.data, pass->tp.salt.len);
  7080.         ptr += pass->tp.salt.len;
  7081.  
  7082.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  7083.  
  7084.         if(SRP_gen_pub(s_srp, &B) != SRP_SUCCESS) {
  7085.             printf("Error generating SRP public value\r\n");
  7086.             SendSRPAuthSB(SRP_REJECT, (void *) "SRP_gen_pub failed", -1);
  7087.             return(AUTH_FAILURE);
  7088.         }
  7089.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
  7090.         return AUTH_SUCCESS;
  7091.  
  7092.     case SRP_EXP:
  7093.         /* Client is sending A to us.  Compute challenge and expected response. */
  7094.         if(s_srp == NULL || B == NULL) {
  7095.             printf("Protocol error: SRP_EXP unexpected\r\n");
  7096.             SendSRPAuthSB(SRP_REJECT, (void *) "Protocol error: unexpected EXP", -1);
  7097.             return(AUTH_FAILURE);
  7098.         }
  7099.  
  7100.         /* Wait until now to send B, since it contains the key to "u" */
  7101.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->length);
  7102.         cstr_free(B);
  7103.         B = NULL;
  7104.  
  7105.         /*
  7106.          * The original SRP AUTH implementation did not protect against
  7107.          * tampering of the auth-type-pairs.  Therefore, when the
  7108.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  7109.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  7110.          * is set we also insert the SSL/TLS client and server finished
  7111.          * messages to ensure that there is no man in the middle attack
  7112.          * underway on the SSL/TLS connection.
  7113.          */
  7114.         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
  7115.             type_check[0] = AUTHTYPE_SRP;
  7116.             type_check[1] = how;
  7117. #ifdef CK_SSL
  7118.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  7119.                 ssl_get_client_finished(&type_check[2],12);
  7120.                 ssl_get_server_finished(&type_check[14],12);
  7121.                 SRP_add_ex_data(s_srp, type_check, 26);
  7122.             } else
  7123. #endif /* CK_SSL */
  7124.                 SRP_add_ex_data(s_srp, type_check, 2);
  7125.         }
  7126.  
  7127.         if(SRP_compute_key(s_srp, &s_key, data, cnt) != SRP_SUCCESS) {
  7128.             printf("Security alert: Trivial session key attempted\r\n");
  7129.             SendSRPAuthSB(SRP_REJECT, (void *) "Trivial session key detected", -1);
  7130.             return(AUTH_FAILURE);
  7131.         }
  7132.         srp_waitresp = 1;
  7133.         return AUTH_SUCCESS;
  7134.  
  7135.     case SRP_RESPONSE:
  7136.         /* Got the response; see if it's correct */
  7137.         if (!srp_waitresp || s_srp == NULL) {
  7138.             if (1)
  7139.           printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  7140.             SendSRPAuthSB(SRP_REJECT,
  7141.               (void *) "Protocol error: unexpected RESPONSE",
  7142.               -1
  7143.               );
  7144.             return(AUTH_FAILURE);
  7145.         }
  7146.     srp_waitresp = 0;    /* we got a response */
  7147.  
  7148.         if (cnt < RESPONSE_LEN) {
  7149.             if (1)
  7150.           printf("Protocol error: malformed response\r\n");
  7151.             SendSRPAuthSB(SRP_REJECT,
  7152.               (void *) "Protocol error: malformed response",
  7153.               -1
  7154.               );
  7155.             return(AUTH_FAILURE);
  7156.         }
  7157.  
  7158.         if(SRP_verify(s_srp, data, cnt) == SRP_SUCCESS) {
  7159.             resp = cstr_new();
  7160.             if(SRP_respond(s_srp, &resp) != SRP_SUCCESS) {
  7161.                 printf("Error computing response\r\n");
  7162.                 SendSRPAuthSB(SRP_REJECT, 
  7163.                               (void *) "Error computing response", -1);
  7164.                 return(AUTH_FAILURE);
  7165.             }
  7166.             SendSRPAuthSB(SRP_ACCEPT, resp->data, resp->length);
  7167.             cstr_free(resp);
  7168.  
  7169. #ifdef CK_ENCRYPTION
  7170. #ifdef CK_SSL
  7171.             if (!(ssl_active_flag || tls_active_flag)) 
  7172. #endif /* CK_SSL */
  7173.             {
  7174.                 skey.type = SK_GENERIC;
  7175.                 skey.length = s_key->length;
  7176.                 skey.data = s_key->data;
  7177.                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  7178.                 cstr_clear_free(s_key);
  7179.                 s_key = NULL;
  7180.             }
  7181. #endif /* CK_ENCRYPTION */
  7182.             auth_finished(AUTH_VALID);
  7183.         }
  7184.         else {
  7185.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  7186.             auth_finished(AUTH_REJECT);
  7187.             return(AUTH_FAILURE);
  7188.         }
  7189.         return AUTH_SUCCESS;
  7190.  
  7191.     default:
  7192.         printf("Unknown SRP option %d\r\n", data[-1]);
  7193.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  7194.         return(AUTH_FAILURE);
  7195.     }
  7196. }
  7197. #endif /* PRE_SRP_1_7_3 */
  7198. #endif /* SRP */
  7199.  
  7200. #ifdef KRB5
  7201. #ifdef KINIT
  7202. /*
  7203.  * clients/kinit/kinit.c
  7204.  *
  7205.  * Copyright 1990 by the Massachusetts Institute of Technology.
  7206.  * All Rights Reserved.
  7207.  *
  7208.  * Export of this software from the United States of America may
  7209.  *   require a specific license from the United States Government.
  7210.  *   It is the responsibility of any person or organization contemplating
  7211.  *   export to obtain such a license before exporting.
  7212.  *
  7213.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  7214.  * distribute this software and its documentation for any purpose and
  7215.  * without fee is hereby granted, provided that the above copyright
  7216.  * notice appear in all copies and that both that copyright notice and
  7217.  * this permission notice appear in supporting documentation, and that
  7218.  * the name of M.I.T. not be used in advertising or publicity pertaining
  7219.  * to distribution of the software without specific, written prior
  7220.  * permission.  M.I.T. makes no representations about the suitability of
  7221.  * this software for any purpose.  It is provided "as is" without express
  7222.  * or implied warranty.
  7223.  *
  7224.  *
  7225.  * Initialize a credentials cache.
  7226.  */
  7227.  
  7228. #define KRB5_DEFAULT_OPTIONS 0
  7229. #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
  7230.  
  7231. static krb5_data tgtname = {
  7232. #ifndef HEIMDAL
  7233.     0,
  7234. #endif /* HEIMDAL */
  7235.     KRB5_TGS_NAME_SIZE,
  7236.     KRB5_TGS_NAME
  7237. };
  7238.  
  7239. /* Internal prototypes */
  7240. _PROTOTYP(static krb5_error_code krb5_validate_tgt,
  7241.         (krb5_context, krb5_ccache,krb5_principal, krb5_data *));
  7242. _PROTOTYP(static krb5_error_code krb5_renew_tgt,
  7243.         (krb5_context, krb5_ccache,
  7244.                         krb5_principal, krb5_data *));
  7245. _PROTOTYP(static krb5_error_code krb5_tgt_gen,
  7246.         (krb5_context, krb5_ccache,
  7247.                         krb5_principal, krb5_data *, int opt));
  7248.  
  7249. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7250. static krb5_error_code KRB5_CALLCONV
  7251. ck_krb5_prompter( krb5_context context,
  7252.                   void *data,
  7253.                   const char *name,
  7254.                   const char *banner,
  7255.                   int num_prompts,
  7256.                   krb5_prompt prompts[])
  7257. {
  7258.     krb5_error_code     errcode = 0;
  7259.     int                 i;
  7260.     char * prompt = NULL;
  7261.     int    len = 0, blen=0, nlen=0;
  7262.  
  7263.     debug(F110,"ck_krb5_prompter name",name,0);
  7264.     debug(F110,"ck_krb5_prompter banner",banner,0);
  7265.     debug(F101,"ck_krb5_prompter num_prompts","",num_prompts);
  7266.  
  7267.     if (name)
  7268.         nlen = strlen(name)+2;
  7269.  
  7270.     if (banner)
  7271.         blen = strlen(banner)+2;
  7272.  
  7273.     for (i = 0; i < num_prompts; i++) {
  7274.         debug(F111,"ck_krb5_prompter prompt",prompts[i].prompt,i);
  7275.  
  7276.         if ( prompt && len < (nlen + blen + strlen(prompts[i].prompt)+2) ) {
  7277.             free(prompt);
  7278.             prompt = NULL;
  7279.         }
  7280.         if ( !prompt )
  7281.             prompt = (char *)malloc(nlen + blen + strlen(prompts[i].prompt)+2);
  7282.         if ( !prompt ) {
  7283.             errcode = KRB5_RC_MALLOC;
  7284.             goto cleanup;
  7285.         }
  7286.         len = nlen + blen + strlen(prompts[i].prompt)+2;
  7287.         ckmakxmsg(prompt,len,
  7288.                  name?name:"",
  7289.                  name?"\r\n":"",
  7290.                  banner?banner:"",
  7291.                  banner?"\r\n":"",
  7292.                  prompts[i].prompt,
  7293.                  ": ",NULL,NULL,NULL,NULL,NULL,NULL);
  7294.  
  7295.         memset(prompts[i].reply->data, 0, prompts[i].reply->length);
  7296.         if (prompts[i].hidden) {
  7297.             readpass(prompt, prompts[i].reply->data,
  7298.                       prompts[i].reply->length);
  7299.         } else {
  7300.             readtext(prompt, prompts[i].reply->data,
  7301.                       prompts[i].reply->length);
  7302.         }
  7303.         prompts[i].reply->length = strlen(prompts[i].reply->data);
  7304.     }
  7305.  
  7306.   cleanup:
  7307.     if ( prompt )
  7308.         free(prompt);
  7309.     if (errcode) {
  7310.         for (i = 0; i < num_prompts; i++) {
  7311.             memset(prompts[i].reply->data, 0, prompts[i].reply->length);
  7312.         }
  7313.     }
  7314.     return errcode;
  7315. }
  7316.  
  7317. /*
  7318.  *      I'm not really sure what to do with this.  The NRL DLLs use a
  7319.  *      different interface for the krb5_prompter callback.  It has
  7320.  *      one less parameter.   This is going to be ugly.
  7321.  */
  7322. static krb5_error_code KRB5_CALLCONV
  7323. ck_NRL_krb5_prompter( krb5_context context,
  7324.                       const char *name,
  7325.                       const char *banner,
  7326.                       int num_prompts,
  7327.                       krb5_prompt prompts[])
  7328. {
  7329.     return(ck_krb5_prompter(context,NULL,name,banner,num_prompts,prompts));
  7330. }
  7331. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7332.  
  7333. #define NO_KEYTAB
  7334.  
  7335. int
  7336. #ifdef CK_ANSIC
  7337. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
  7338.                  struct krb4_init_data * k4_init)
  7339. #else
  7340. ck_krb5_initTGT(op,init,k4_init)
  7341.     krb_op_data * op; struct krb5_init_data * init;
  7342.     struct krb4_init_data * k4_init;
  7343. #endif /* CK_ANSIC*/
  7344. {
  7345.     krb5_context kcontext;
  7346.     krb5_ccache ccache = NULL;
  7347.     krb5_deltat lifetime = KRB5_DEFAULT_LIFE;    /* -l option */
  7348.     krb5_timestamp starttime = 0;
  7349.     krb5_deltat rlife = 0;
  7350.     int options = KRB5_DEFAULT_OPTIONS;
  7351.     int option;
  7352.     int errflg = 0;
  7353.     krb5_error_code code;
  7354.     krb5_principal me=NULL;
  7355.     krb5_principal server=NULL;
  7356.     krb5_creds my_creds;
  7357.     krb5_timestamp now;
  7358. #ifndef HEIMDAL
  7359.     krb5_address **addrs = (krb5_address **)0;
  7360. #endif /* HEIMDAL */
  7361.     int addr_count=0;
  7362.     int i,j;
  7363. #ifndef NO_KEYTAB
  7364.     int use_keytab = 0;            /* -k option */
  7365.     krb5_keytab keytab = NULL;
  7366. #endif /* NO_KEYTAB */
  7367.     struct passwd *pw = 0;
  7368.     int pwsize;
  7369.     char *client_name=NULL, principal[256]="", realm[256]="", numstr[40]="";
  7370.     char *password=NULL, passwd[80]="";
  7371. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7372.     krb5_get_init_creds_opt opts;
  7373. #endif
  7374.     char * name;
  7375.     int len;
  7376.  
  7377.     if ( !ck_krb5_is_installed() )
  7378.         return(-1);
  7379.  
  7380. #ifdef COMMENT
  7381.     printf("Kerberos V initialization\r\n");
  7382. #endif /* COMMENT */
  7383.  
  7384.     code = krb5_init_context(&kcontext);
  7385.     if (code) {
  7386.         com_err("krb5_kinit",code,"while init_context");
  7387.         krb5_errno = code;
  7388.         makestr(&krb5_errmsg,error_message(krb5_errno));
  7389.         return(-1);
  7390.     }
  7391.  
  7392.     debug(F110,"krb5_init","krb5_init_context",0);
  7393.  
  7394.     if ((code = krb5_timeofday(kcontext, &now))) {
  7395.         com_err("krb5_kinit",code,"while getting time of day");
  7396.         goto exit_k5_init;
  7397.     }
  7398.  
  7399. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7400.     memset(&opts, 0, sizeof(opts));
  7401.     krb5_get_init_creds_opt_init(&opts);
  7402.     debug(F110,"krb5_init","krb5_get_init_creds_opt_init",0);
  7403. #endif
  7404.  
  7405.     if ( init->renewable ) {
  7406.         options |= KDC_OPT_RENEWABLE;
  7407.         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->renewable),"m",NULL,NULL);
  7408. #ifdef HEIMDAL
  7409.         code = -1;
  7410. #else /* HEIMDAL */
  7411.         code = krb5_string_to_deltat(numstr, &rlife);
  7412. #endif /* HEIMDAL */
  7413.         if (code != 0 || rlife == 0) {
  7414.             printf("Bad renewable time value %s\r\n", numstr);
  7415.             errflg++;
  7416.         }
  7417. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7418.         krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
  7419. #endif
  7420.     }
  7421.     if ( init->renew ) {
  7422.         /* renew the ticket */
  7423.         options |= KDC_OPT_RENEW;
  7424.     }
  7425.  
  7426.     if ( init->validate ) {
  7427.         /* validate the ticket */
  7428.         options |= KDC_OPT_VALIDATE;
  7429.     }
  7430.     if ( init->proxiable ) {
  7431.         options |= KDC_OPT_PROXIABLE;
  7432. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7433.         krb5_get_init_creds_opt_set_proxiable(&opts, 1);
  7434. #endif
  7435.     }
  7436.     if ( init->forwardable ) {
  7437.         options |= KDC_OPT_FORWARDABLE;
  7438. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7439.         krb5_get_init_creds_opt_set_forwardable(&opts, 1);
  7440. #endif
  7441.     }
  7442. #ifndef NO_KEYTAB
  7443.     if (  ) {
  7444.         use_keytab = 1;
  7445.     }
  7446.     if (  ) {
  7447.         if (keytab == NULL && keytab_name != NULL) {
  7448.             code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
  7449.             if (code != 0) {
  7450.                 debug(F111,"krb5_init resolving keytab",
  7451.                          keytab_name,code);
  7452.                 errflg++;
  7453.             }
  7454.         }
  7455.     }
  7456. #endif /* NO_KEYTAB */
  7457.     if ( init->lifetime ) {
  7458.         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->lifetime),"m",NULL,NULL);
  7459. #ifdef HEIMDAL
  7460.         code = -1;
  7461. #else /* HEIMDAL */
  7462.         code = krb5_string_to_deltat(numstr, &lifetime);
  7463. #endif /* HEIMDAL */
  7464.         if (code != 0 || lifetime == 0) {
  7465.             printf("Bad lifetime value %s\r\n", numstr);
  7466.             errflg++;
  7467.         }
  7468. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7469.         krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
  7470. #endif
  7471.     }
  7472.     if ( init->postdate ) {
  7473.         /* Convert cmdate() to a time_t value */
  7474.         struct tm * time_tm;
  7475.         struct tm * cmdate2tm(char *,int);
  7476.         time_tm = cmdate2tm(init->postdate,0);
  7477.         if ( time_tm )
  7478.             starttime = (krb5_timestamp) mktime(time_tm);
  7479.  
  7480.         if (code != 0 || starttime == 0 || starttime == -1) {
  7481.             krb5_deltat ktmp;
  7482. #ifdef HEIMDAL
  7483.             code = -1;
  7484. #else /* HEIMDAL */
  7485.             code = krb5_string_to_deltat(init->postdate, &ktmp);
  7486. #endif /* HEIMDAL */
  7487.             if (code == 0 && ktmp != 0) {
  7488.         starttime = now + ktmp;
  7489.         options |= KDC_OPT_POSTDATED;
  7490.             } else {
  7491.         printf("Bad postdate start time value %s\r\n",
  7492.                         init->postdate);
  7493.         errflg++;
  7494.             }
  7495.         } else {
  7496.             options |= KDC_OPT_POSTDATED;
  7497.         }
  7498.     }
  7499.  
  7500.     debug(F110,"krb5_init searching for ccache",op->cache,0);
  7501.  
  7502.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  7503.     if (code != 0) {
  7504.         com_err("krb5_kinit",code,"while getting default ccache");
  7505.         goto exit_k5_init;
  7506.     }
  7507.  
  7508.     /* This is our realm unless it is changed */
  7509.     ckstrncpy(realm,init->realm ? init->realm : krb5_d_realm, 256);
  7510.  
  7511. #ifdef BETATEST
  7512.     /* This code is going to take the realm and attempt to correct */
  7513.     /* the case.                                                   */
  7514.     {
  7515.         profile_t profile;
  7516.  
  7517.         code = krb5_get_profile(kcontext, &profile);
  7518.         if ( !code ) {
  7519.             const char  *names[4];
  7520.             char ** realms;
  7521.             int found = 0;
  7522.  
  7523.             names[0] = "realms";
  7524.             names[1] = NULL;
  7525.  
  7526.             code = profile_get_subsection_names(profile,names,&realms);
  7527.             if ( code == 0 ) {
  7528.                 int i=0;
  7529.                 while ( realms[i] ) {
  7530.                     if (ckstrcmp(realm,realms[i],-1,0) == 0) {
  7531.                         strcpy(realm,realms[i]);
  7532.                         found = 1;
  7533.                         break;
  7534.                     }
  7535.                     i++;
  7536.                 }
  7537.             }
  7538.  
  7539. #ifdef CK_DNS_SRV
  7540.             if ( !found ) {
  7541.                 char * dns_realm = NULL;
  7542.  
  7543.                 /* We did not find the realm in the profile so let's try DNS */
  7544.                 locate_txt_rr("_kerberos",realm,&dns_realm);
  7545.                 if ( dns_realm &&
  7546.                      ckstrcmp(realm,dns_realm,-1,0) == 0 &&
  7547.                      ckstrcmp(realm,dns_realm,-1,1) != 0
  7548.                      ) {
  7549.                     ckstrncpy(realm,dns_realm,256);
  7550.                     free(dns_realm);
  7551.                 }
  7552.             }
  7553. #endif /* CK_DNS_SRV */
  7554.         }
  7555.  
  7556.         if (init->realm &&
  7557.              ckstrcmp(realm,init->realm,-1,0) == 0 &&
  7558.              ckstrcmp(realm,init->realm,-1,1) != 0)
  7559.             strcpy(init->realm,realm);
  7560.         if (ckstrcmp(realm,krb5_d_realm,-1,0) == 0 &&
  7561.              ckstrcmp(realm,krb5_d_realm,-1,1) != 0)
  7562.             strcpy(krb5_d_realm,realm);
  7563.     }
  7564. #endif /* BETATEST */
  7565.  
  7566.     if (init->principal == NULL) {       /* No principal name specified */
  7567. #ifndef NO_KEYTAB
  7568.         if (use_keytab) {
  7569.             /* Use the default host/service name */
  7570.             code = krb5_sname_to_principal(kcontext, NULL, NULL,
  7571.                                             KRB5_NT_SRV_HST, &me);
  7572.             if (code == 0 &&
  7573.                 krb5_princ_realm(kcontext, me)->length < sizeof(realm))
  7574.             {
  7575.                 /* Save the realm */
  7576.                 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  7577.                         krb5_princ_realm(kcontext, me)->length); /* safe */
  7578.                 realm[krb5_princ_realm(kcontext, me)->length]='\0';
  7579.             } else {
  7580.                 com_err("krb5_kinit",
  7581.             code,
  7582.             "when creating default server principal name");
  7583.                 goto exit_k5_init;
  7584.             }
  7585.         } else
  7586. #endif /* NO_KEYTAB */
  7587.         {
  7588.             int len;
  7589.             char * name;
  7590.  
  7591.             /* Get default principal from cache if one exists */
  7592.             code = krb5_cc_get_principal(kcontext, ccache, &me);
  7593. #ifdef HEIMDAL
  7594.             name = me->realm;
  7595.             len = strlen(name);
  7596. #else /* HEIMDAL */
  7597.             len = krb5_princ_realm(kcontext, me)->length;
  7598.             name = krb5_princ_realm(kcontext, me)->data;
  7599. #endif /* HEIMDAL */
  7600.             if (code == 0 && len < sizeof(realm))
  7601.             {
  7602.                 /* Save the realm */
  7603.                 memcpy(realm,name,len); /* safe */
  7604.                 realm[len]='\0';
  7605.             } else {
  7606. #ifdef HAVE_PWD_H
  7607.                 /* Else search passwd file for client */
  7608.  
  7609.                 pw = getpwuid((int) getuid());
  7610.                 if (pw) {
  7611.                     char princ_realm[256];
  7612.                     if ( (strlen(pw->pw_name) + strlen(realm) + 1) > 255 )
  7613.                         goto exit_k5_init;
  7614.  
  7615.                     ckstrncpy(principal,pw->pw_name,256);
  7616.                     ckstrncpy(princ_realm,pw->pw_name,256);
  7617.                     ckstrncat(princ_realm,"@",256);
  7618.                     ckstrncat(princ_realm,realm,256);
  7619.  
  7620.                     if ((code = krb5_parse_name(kcontext,princ_realm,&me))) {
  7621.                         krb5_errno = code;
  7622.                         com_err("krb5_kinit",code,"when parsing name",
  7623.                                   princ_realm);
  7624.                         goto exit_k5_init;
  7625.                     }
  7626.                 } else {
  7627.                     printf(
  7628.                         "Unable to identify user from password file\r\n");
  7629.                     goto exit_k5_init;
  7630.                 }
  7631. #else /* HAVE_PWD_H */
  7632.                 printf("Unable to identify user\r\n");
  7633.                 goto exit_k5_init;
  7634. #endif /* HAVE_PWD_H */
  7635.             }
  7636.         }
  7637.  
  7638. #ifdef HEIMDAL
  7639.         len = me->name.name_string.len;
  7640.         name = *me->name.name_string.val;
  7641. #else /* HEIMDAL */
  7642.         len = krb5_princ_name(kcontext, me)->length;
  7643.         name = krb5_princ_name(kcontext, me)->data;
  7644. #endif /* HEIMDAL */
  7645.         if ( len < sizeof(principal) ) {
  7646.             memcpy(principal,name,len);     /* safe */
  7647.             principal[len]='\0';
  7648.         }
  7649.     } /* Use specified name */
  7650.     else {
  7651.         char princ_realm[256];
  7652.         if ( (strlen(init->principal) +
  7653.           (init->instance ? strlen(init->instance)+1 : 0) +
  7654.           strlen(realm)
  7655.           + 2) > 255 )
  7656.              goto exit_k5_init;
  7657.  
  7658.         ckstrncpy(principal,init->principal,256);
  7659.         ckstrncpy(princ_realm,init->principal,256);
  7660.         if (init->instance) {
  7661.             ckstrncat(princ_realm,"/",256);
  7662.             ckstrncat(princ_realm,init->instance,256);
  7663.         }
  7664.         if (realm[0]) {
  7665.           ckstrncat(princ_realm,"@",256);
  7666.           ckstrncat(princ_realm,realm,256);
  7667.         }
  7668.         if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
  7669.             com_err("krb5_kinit",code,"when parsing name",princ_realm);
  7670.             goto exit_k5_init;
  7671.         }
  7672.     }
  7673.  
  7674.     if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
  7675.     com_err("krb5_kinit",code,"when unparsing name");
  7676.         goto exit_k5_init;
  7677.     }
  7678.     debug(F110,"krb5_init client_name",client_name,0);
  7679.  
  7680.  
  7681.     memset((char *)&my_creds, 0, sizeof(my_creds));
  7682.     my_creds.client = me;
  7683.  
  7684.     if (init->service == NULL) {
  7685.         if ((code =
  7686.          krb5_build_principal_ext(kcontext,
  7687.                       &server,
  7688.                       strlen(realm),realm,
  7689.                       tgtname.length, tgtname.data,
  7690.                       strlen(realm),realm,
  7691.                       0))) {
  7692.             com_err("krb5_kinit",code,"while building server name");
  7693.             goto exit_k5_init;
  7694.         }
  7695.     } else {
  7696.         if (code = krb5_parse_name(kcontext, init->service, &server)) {
  7697.             com_err("krb5_kinit",code,"while parsing service name",
  7698.             init->service);
  7699.             goto exit_k5_init;
  7700.         }
  7701.     }
  7702.  
  7703.     my_creds.server = server;
  7704.  
  7705.     if (options & KDC_OPT_POSTDATED) {
  7706.         my_creds.times.starttime = starttime;
  7707.         my_creds.times.endtime = starttime + lifetime;
  7708.     } else {
  7709.         my_creds.times.starttime = 0;    /* start timer when request
  7710.                        gets to KDC */
  7711.         my_creds.times.endtime = now + lifetime;
  7712.     }
  7713.     if (options & KDC_OPT_RENEWABLE) {
  7714.     my_creds.times.renew_till = now + rlife;
  7715.     } else
  7716.     my_creds.times.renew_till = 0;
  7717.  
  7718.     if (options & KDC_OPT_VALIDATE) {
  7719.         krb5_data outbuf;
  7720.  
  7721. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7722.         code = krb5_get_validated_creds(kcontext,
  7723.                     &my_creds, me, ccache, init->service);
  7724.         if ( code == -1 )
  7725. #endif
  7726.         {
  7727. #ifdef HEIMDAL
  7728.             printf("?validate not implemented\r\n");
  7729.             code = -1;
  7730.             goto exit_k5_init;
  7731. #else /* HEIMDAL */
  7732.             code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
  7733. #endif /* HEIMDAL */
  7734.         }
  7735.         if (code) {
  7736.             com_err("krb5_kinit",code,"validating tgt");
  7737.             goto exit_k5_init;
  7738.         }
  7739.     /* should be done... */
  7740.         goto exit_k5_init;
  7741.     }
  7742.  
  7743.     if (options & KDC_OPT_RENEW) {
  7744.         krb5_data outbuf;
  7745.  
  7746. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7747.         code = krb5_get_renewed_creds(kcontext,
  7748.                       &my_creds, me, ccache, init->service);
  7749.         if ( code == -1 )
  7750. #endif
  7751.         {
  7752. #ifdef HEIMDAL
  7753.             printf("?renew not implemented\r\n");
  7754.             code = -1;
  7755.             goto exit_k5_init;
  7756. #else /* HEIMDAL */
  7757.             code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
  7758. #endif /* HEIMDAL */
  7759.         }
  7760.     if (code) {
  7761.             com_err("krb5_kinit",code,"while renewing tgt");
  7762.             goto exit_k5_init;
  7763.     }
  7764.     /* should be done... */
  7765.         goto exit_k5_init;
  7766.     }
  7767.  
  7768. #ifndef HEIMDAL
  7769.     if ( init->addrs && !init->no_addresses ) {
  7770.         /* construct an array of krb5_address structs to pass to get_in_tkt */
  7771.         /* include both the local ip addresses as well as any other that    */
  7772.         /* are specified.                                                   */
  7773.         unsigned long ipaddr;
  7774.  
  7775.         for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
  7776.             if ( init->addrs[addr_count] == NULL )
  7777.                 break;
  7778.  
  7779.         if (addr_count > 0) {
  7780.             krb5_address ** local_addrs=NULL;
  7781.             krb5_os_localaddr(kcontext, &local_addrs);
  7782.             i = 0;
  7783.             while ( local_addrs[i] )
  7784.                 i++;
  7785.             addr_count += i;
  7786.  
  7787.             addrs = (krb5_address **)
  7788.           malloc((addr_count+1) * sizeof(krb5_address));
  7789.             if ( !addrs ) {
  7790.                 krb5_free_addresses(kcontext, local_addrs);
  7791.                 goto exit_k5_init;
  7792.             }
  7793.             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
  7794.             i = 0;
  7795.             while ( local_addrs[i] ) {
  7796.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  7797.                 if (addrs[i] == NULL) {
  7798.                     krb5_free_addresses(kcontext, local_addrs);
  7799.                     goto exit_k5_init;
  7800.                 }
  7801.  
  7802.                 addrs[i]->magic = local_addrs[i]->magic;
  7803.                 addrs[i]->addrtype = local_addrs[i]->addrtype;
  7804.                 addrs[i]->length = local_addrs[i]->length;
  7805.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  7806.                 if (!addrs[i]->contents) {
  7807.                     krb5_free_addresses(kcontext, local_addrs);
  7808.                     goto exit_k5_init;
  7809.                 }
  7810.  
  7811.                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
  7812.                         local_addrs[i]->length);        /* safe */
  7813.                 i++;
  7814.             }
  7815.             krb5_free_addresses(kcontext, local_addrs);
  7816.  
  7817.             for ( j=0;i<addr_count;i++,j++ ) {
  7818.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  7819.                 if (addrs[i] == NULL)
  7820.                     goto exit_k5_init;
  7821.  
  7822.                 addrs[i]->magic = KV5M_ADDRESS;
  7823.                 addrs[i]->addrtype = AF_INET;
  7824.                 addrs[i]->length = 4;
  7825.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  7826.                 if (!addrs[i]->contents)
  7827.                     goto exit_k5_init;
  7828.  
  7829.                 ipaddr = inet_addr(init->addrs[j]);
  7830.                 memcpy(addrs[i]->contents,&ipaddr,4);   /* safe */
  7831.             }
  7832. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7833.             krb5_get_init_creds_opt_set_address_list(&opts,addrs);
  7834. #endif
  7835.         }
  7836.      }
  7837. #endif /* !HEIMDAL */
  7838. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7839.     if ( init->no_addresses )
  7840.         krb5_get_init_creds_opt_set_address_list(&opts,NULL);
  7841. #endif
  7842.  
  7843. #ifndef NO_KEYTAB
  7844.     if (!use_keytab)
  7845. #endif
  7846.     {
  7847.         if ( init->password ) {
  7848.             pwsize = strlen(init->password);
  7849.             if ( pwsize )
  7850.                 password = init->password;
  7851.         } else if (init->getk4 && k4_init) {
  7852.             /* When we are requesting that K4 tickets be automatically */
  7853.             /* acquired when K5 tickets are acquired, we must get the  */
  7854.             /* password up front.                                      */
  7855.             char prmpt[256];
  7856.             extern char * k5prprompt;
  7857.             extern char * k5pwprompt;
  7858.  
  7859.             if ( k5pwprompt && k5pwprompt[0] &&
  7860.                  (strlen(k5pwprompt) + strlen(principal) +
  7861.                   strlen(realm) - 4) < sizeof(prmpt)) {
  7862.                 sprintf(prmpt,k5pwprompt,principal,realm);
  7863.             } else
  7864.                 ckmakxmsg(prmpt,sizeof(prmpt),
  7865.                            k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  7866.                            "Kerberos 5 Password for ",
  7867.                            principal,"@",realm,": ",
  7868.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL
  7869.                            );
  7870.             readpass(prmpt,passwd,80);
  7871.             password = passwd;
  7872.  
  7873.             if ( k4_init->password == NULL )
  7874.                 makestr(&k4_init->password,passwd);
  7875.         }
  7876. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7877.         debug(F100,"krb5_init calling krb5_get_init_creds_password()","",0);
  7878. #ifdef OS2
  7879.         if ( is_NRL_KRB5() )
  7880.             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
  7881.                                                  password,
  7882.                                                  (void *)ck_NRL_krb5_prompter,
  7883.                                                  NULL,
  7884.                                                  starttime, init->service,
  7885.                                                  &opts);
  7886.         else
  7887. #endif /* OS2 */
  7888.             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
  7889.                                                  password,
  7890.                                                  ck_krb5_prompter,
  7891.                                                  NULL,
  7892.                                                  starttime, init->service,
  7893.                                                  &opts);
  7894.         debug(F111,"krb5_init","krb5_get_init_creds_password()",code);
  7895.  
  7896.         if ( code == -1 )
  7897.         {
  7898.             if (!password) {
  7899.                 char prmpt[256];
  7900.                 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
  7901.                           client_name,": ",NULL);
  7902.                 readpass(prmpt,passwd,80);
  7903.                 password = passwd;
  7904.             }
  7905.  
  7906.             if ( !password[0] ) {
  7907.                 debug(F111,"krb5_init","no password specified",0);
  7908.                 printf("A password must be specified for %s.\r\n",client_name);
  7909.                 goto exit_k5_init;
  7910.             }
  7911.             code = krb5_get_in_tkt_with_password(kcontext, options,
  7912. #ifdef HEIMDAL
  7913.                                                   NULL,
  7914. #else /* HEIMDAL */
  7915.                                             init->no_addresses ? NULL :addrs,
  7916. #endif /* HEIMDAL */
  7917.                                                   NULL, NULL,
  7918.                                                   password,
  7919.                                                   NULL, &my_creds, NULL);
  7920.             if ( code )
  7921.                 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
  7922.         }
  7923. #else /* KRB5_HAVE_GET_INIT_CREDS */
  7924.         if (!password) {
  7925.             char prmpt[256];
  7926.             ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
  7927.                       client_name,": ",NULL);
  7928.             readpass(prmpt,passwd,80);
  7929.             password = passwd;
  7930.         }
  7931.  
  7932.         if ( !password[0] ) {
  7933.             debug(F111,"krb5_init","no password specified",0);
  7934.             printf("A password must be specified for %s.\r\n",client_name);
  7935.             goto exit_k5_init;
  7936.         }
  7937.         code = krb5_get_in_tkt_with_password(kcontext, options,
  7938. #ifdef HEIMDAL
  7939.                                               NULL,
  7940. #else /* HEIMDAL */
  7941.                                             init->no_addresses ? NULL :addrs,
  7942. #endif /* HEIMDAL */
  7943.                                               NULL, NULL,
  7944.                                               password,
  7945.                                               NULL, &my_creds, NULL);
  7946.         if ( code )
  7947.             debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
  7948. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7949.  
  7950.         if ( init->password && pwsize > 0 )
  7951.             memset(init->password, 0, pwsize);
  7952.         memset(passwd,0,80);
  7953.     }
  7954. #ifndef NO_KEYTAB
  7955.     else {
  7956. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7957.         code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
  7958.                                            starttime, init->service,
  7959.                                            &opts);
  7960. #ifdef OS2
  7961.         if ( code == -1)
  7962.             code = krb5_get_in_tkt_with_keytab(kcontext, options,
  7963.                                            init->no_addresses ? NULL :addrs,
  7964.                                                 NULL, NULL, keytab, NULL,
  7965.                                                 &my_creds, 0);
  7966. #endif /* OS2 */
  7967. #else /* KRB5_HAVE_GET_INIT_CREDS */
  7968.         code = krb5_get_in_tkt_with_keytab(kcontext, options,
  7969. #ifdef HEIMDAL
  7970.                                                   NULL,
  7971. #else /* HEIMDAL */
  7972.                                             init->no_addresses ? NULL :addrs,
  7973. #endif /* HEIMDAL */
  7974.                                             NULL, NULL, keytab, NULL,
  7975.                                             &my_creds, 0);
  7976. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7977.     }
  7978. #endif
  7979.  
  7980.     if (code) {
  7981.     switch (code) {
  7982.         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
  7983.         printf("Password incorrect\r\n");
  7984.             goto exit_k5_init;
  7985.         case KRB5KRB_AP_ERR_V4_REPLY:
  7986.             if (init->getk4 && k4_init) {
  7987.                 printf("Kerberos 5 Tickets not support by server.  ");
  7988.                 printf("A version 4 Ticket will be requested.\r\n");
  7989.             }
  7990.             goto exit_k5_init;
  7991.         default:
  7992.             goto exit_k5_init;
  7993.         }
  7994.     }
  7995.  
  7996.     debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
  7997.  
  7998.     code = krb5_cc_initialize (kcontext, ccache, me);
  7999.     if ( code == KRB5_CC_BADNAME ) {
  8000.         /* This is a really ugly hack that should not have to be here.
  8001.          * krb5_cc_initialize should not fail with an error if the
  8002.          * cache already exists.  The reason the problem is occuring
  8003.          * is that the krb5 library is no longer calling cc_destroy()
  8004.          * when cc_initialize() is called and the CCAPI implementation
  8005.          * on Windows has not yet been corrected to handle it.  To
  8006.          * ensure that K95 will continue to work with both we will call
  8007.          * cc_destroy() if the cc_initialize() call fails with a BADNAME
  8008.          * error.  If the cc_destroy() is successful, we will try again.
  8009.          */
  8010.  
  8011.         debug(F100,"krb5_init calling krb5_cc_destroy()","",0);
  8012.         code = krb5_cc_destroy (kcontext, ccache);
  8013.         if ( !code ) {
  8014.             debug(F100,"krb5_init calling k5_get_ccache()","",0);
  8015.             code = k5_get_ccache(kcontext,&ccache,op->cache);
  8016.             debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
  8017.             code = krb5_cc_initialize (kcontext, ccache, me);
  8018.         } else
  8019.             code = KRB5_CC_BADNAME;
  8020.     }
  8021.     if (code) {
  8022.         com_err("krb5_kinit",code,"when initializing cache",op->cache);
  8023.         goto exit_k5_init;
  8024.     }
  8025.  
  8026.     debug(F100,"krb5_init calling krb5_cc_store_cred()","",0);
  8027.     code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
  8028.     if (code) {
  8029.         com_err("krb5_kinit",code,"while storing credentials");
  8030.         goto exit_k5_init;
  8031.     }
  8032.  
  8033. exit_k5_init:
  8034.     debug(F100,"krb5_init exit_k5_init","",0);
  8035.  
  8036. #ifndef HEIMDAL
  8037.     /* Free krb5_address structures if we created them */
  8038.     if ( addrs ) {
  8039.         for ( i=0;i<addr_count;i++ ) {
  8040.             if ( addrs[i] ) {
  8041.                 if ( addrs[i]->contents )
  8042.                     free(addrs[i]->contents);
  8043.                 free(addrs[i]);
  8044.             }
  8045.         }
  8046.     }
  8047. #endif /* HEIMDAL */
  8048.  
  8049.     /* my_creds is pointing at server */
  8050.     debug(F100,"krb5_init calling krb5_free_principal()","",0);
  8051.     krb5_free_principal(kcontext, server);
  8052.     debug(F100,"krb5_init calling krb5_cc_close()","",0);
  8053.     krb5_cc_close(kcontext,ccache);
  8054.     debug(F100,"krb5_init calling krb5_free_context()","",0);
  8055.     krb5_free_context(kcontext);
  8056.  
  8057.     krb5_errno = code;
  8058.     makestr(&krb5_errmsg,krb5_errno ? error_message(krb5_errno) : "OK");
  8059.  
  8060.     if ( init->getk4 && k4_init ) {
  8061.         int k4rc = ck_krb4_initTGT(op,k4_init);
  8062.         return (k4rc < 0 ? -1 : 0);
  8063.     }
  8064.  
  8065.     printf("Result from realm %s: %s\r\n",realm,
  8066.             code?error_message(code):"OK");
  8067.     return(code?-1:0);
  8068. }
  8069.  
  8070. #ifndef HEIMDAL
  8071. #define VALIDATE 0
  8072. #define RENEW 1
  8073.  
  8074. /* stripped down version of krb5_mk_req */
  8075. static krb5_error_code
  8076. #ifdef CK_ANSIC
  8077. krb5_validate_tgt( krb5_context context,
  8078.                    krb5_ccache ccache,
  8079.                    krb5_principal     server, /* tgtname */
  8080.                    krb5_data *outbuf )
  8081. #else
  8082. krb5_validate_tgt(context, ccache, server, outbuf)
  8083.      krb5_context context;
  8084.      krb5_ccache ccache;
  8085.      krb5_principal     server; /* tgtname */
  8086.      krb5_data *outbuf;
  8087. #endif
  8088. {
  8089.     return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
  8090. }
  8091.  
  8092. /* stripped down version of krb5_mk_req */
  8093. static krb5_error_code
  8094. #ifdef CK_ANSIC
  8095. krb5_renew_tgt(krb5_context context,
  8096.                 krb5_ccache ccache,
  8097.                 krb5_principal      server, /* tgtname */
  8098.                 krb5_data *outbuf)
  8099. #else
  8100. krb5_renew_tgt(context, ccache, server, outbuf)
  8101.      krb5_context context;
  8102.      krb5_ccache ccache;
  8103.      krb5_principal      server; /* tgtname */
  8104.      krb5_data *outbuf;
  8105. #endif
  8106. {
  8107.     return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
  8108. }
  8109.  
  8110.  
  8111. /* stripped down version of krb5_mk_req */
  8112. static krb5_error_code
  8113. #ifdef CK_ANSIC
  8114. krb5_tgt_gen(krb5_context context,
  8115.               krb5_ccache ccache,
  8116.               krb5_principal      server, /* tgtname */
  8117.               krb5_data *outbuf,
  8118.               int opt)
  8119. #else
  8120. krb5_tgt_gen(context, ccache, server, outbuf, opt)
  8121.      krb5_context context;
  8122.      krb5_ccache ccache;
  8123.      krb5_principal      server; /* tgtname */
  8124.      krb5_data *outbuf;
  8125.      int opt;
  8126. #endif
  8127. {
  8128.     krb5_error_code       retval;
  8129.     krb5_creds         * credsp;
  8130.     krb5_creds           creds;
  8131.  
  8132.     /* obtain ticket & session key */
  8133.     memset((char *)&creds, 0, sizeof(creds));
  8134.     if ((retval = krb5_copy_principal(context, server, &creds.server)))
  8135.     goto cleanup;
  8136.  
  8137.     if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
  8138.     goto cleanup_creds;
  8139.  
  8140.     if (opt == VALIDATE) {
  8141.     if ((retval = krb5_get_credentials_validate(context, 0,
  8142.                             ccache, &creds, &credsp)))
  8143.       goto cleanup_creds;
  8144.     } else {
  8145.     if ((retval = krb5_get_credentials_renew(context, 0,
  8146.                          ccache, &creds, &credsp)))
  8147.       goto cleanup_creds;
  8148.     }
  8149.  
  8150.     /* we don't actually need to do the mk_req, just get the creds. */
  8151. cleanup_creds:
  8152.     krb5_free_cred_contents(context, &creds);
  8153.  
  8154. cleanup:
  8155.  
  8156.     return retval;
  8157. }
  8158. #endif /* HEIMDAL */
  8159. #endif /* KINIT */
  8160. #ifdef KDESTROY
  8161. int
  8162. #ifdef CK_ANSIC
  8163. ck_krb5_destroy(struct krb_op_data * op)
  8164. #else
  8165. ck_krb5_destroy(op) struct krb_op_data * op;
  8166. #endif
  8167. {
  8168.     krb5_context kcontext;
  8169.     krb5_error_code retval;
  8170.     int c;
  8171.     krb5_ccache ccache = NULL;
  8172.     char *cache_name = NULL;
  8173.     int code;
  8174.     int errflg=0;
  8175.     int quiet = 0;
  8176.  
  8177.     if ( !ck_krb5_is_installed() )
  8178.         return(-1);
  8179.  
  8180.     code = krb5_init_context(&kcontext);
  8181.     if (code) {
  8182.         debug(F101,"ck_krb5_destroy while initializing krb5","",code);
  8183.         krb5_errno = code;
  8184.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8185.         return(-1);
  8186.     }
  8187.  
  8188.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  8189.     if (code != 0) {
  8190.         debug(F101,"ck_krb5_destroy while getting ccache",
  8191.                "",code);
  8192.         krb5_free_context(kcontext);
  8193.         krb5_errno = code;
  8194.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8195.         return(-1);
  8196.     }
  8197.  
  8198.     code = krb5_cc_destroy (kcontext, ccache);
  8199.     if (code != 0) {
  8200.     debug(F101,"ck_krb5_destroy while destroying cache","",code);
  8201.         if ( code == KRB5_FCC_NOFILE )
  8202.             printf("No ticket cache to destroy.\r\n");
  8203.         else
  8204.             printf("Ticket cache NOT destroyed!\r\n");
  8205.         krb5_cc_close(kcontext,ccache);
  8206.         krb5_free_context(kcontext);
  8207.         krb5_errno = code;
  8208.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8209.     return(-1);
  8210.     }
  8211.  
  8212.     printf("Tickets destroyed.\r\n");
  8213.     /* Do not call krb5_cc_close() because cache has been destroyed */
  8214.     krb5_free_context(kcontext);
  8215.     krb5_errno = 0;
  8216.     makestr(&krb5_errmsg,"OK");
  8217.     return (0);
  8218. }
  8219. #else /* KDESTROY */
  8220. #ifdef KRB5
  8221. int
  8222. #ifdef CK_ANSIC
  8223. ck_krb5_destroy(struct krb_op_data * op)
  8224. #else
  8225. ck_krb5_destroy(op) struct krb_op_data * op;
  8226. #endif
  8227. {
  8228.     printf("?Not implemented.\r\n");
  8229.     return(-1);
  8230. }
  8231. #endif /* KRB5 */
  8232. #endif /* KDESTROY */
  8233. #ifndef KLIST
  8234. #ifdef KRB5
  8235. int
  8236. #ifdef CK_ANSIC
  8237. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  8238. #else
  8239. ck_krb5_list_creds(op,lc)
  8240.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  8241. #endif
  8242. {
  8243.     printf("?Not implemented.\r\n");
  8244.     return(-1);
  8245. }
  8246. #endif /* KRB5 */
  8247. #else /* KLIST */
  8248. static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
  8249. static int show_etype = 0, show_addr = 0;
  8250. static char *defname;
  8251. static char *progname;
  8252. static krb5_int32 now;
  8253. static int timestamp_width;
  8254.  
  8255. _PROTOTYP(static char * etype_string, (krb5_enctype ));
  8256. _PROTOTYP(static void show_credential,(krb5_context,krb5_creds *));
  8257. _PROTOTYP(static int do_ccache, (krb5_context,char *));
  8258. _PROTOTYP(static int do_keytab, (krb5_context,char *));
  8259. _PROTOTYP(static void printtime, (time_t));
  8260. _PROTOTYP(static void fillit, (int, int));
  8261.  
  8262. #define DEFAULT 0
  8263. #define CCACHE 1
  8264. #define KEYTAB 2
  8265.  
  8266. int
  8267. #ifdef CK_ANSIC
  8268. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  8269. #else
  8270. ck_krb5_list_creds(op,lc)
  8271.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  8272. #endif
  8273. {
  8274.     krb5_context kcontext;
  8275.     krb5_error_code retval;
  8276.     int code;
  8277.     char *name = op->cache;
  8278.     int mode;
  8279.  
  8280.     if ( !ck_krb5_is_installed() )
  8281.         return(-1);
  8282.  
  8283.     code = krb5_init_context(&kcontext);
  8284.     if (code) {
  8285.         debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
  8286.         krb5_errno = code;
  8287.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8288.         return(-1);
  8289.     }
  8290.  
  8291.     name = op->cache;
  8292.     mode = DEFAULT;
  8293.     show_flags = 0;
  8294.     show_time = 0;
  8295.     status_only = 0;
  8296.     show_keys = 0;
  8297.     show_etype = 0;
  8298.     show_addr = 0;
  8299.  
  8300.     show_flags = lc->flags;
  8301.     show_etype = lc->encryption;
  8302.     show_addr  = lc->addr;
  8303.     show_time = 1;
  8304.     show_keys = 1;
  8305.     mode = CCACHE;
  8306.  
  8307.     if ((code = krb5_timeofday(kcontext, &now))) {
  8308.         if (!status_only)
  8309.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  8310.                    "",code);
  8311.         krb5_free_context(kcontext);
  8312.         krb5_errno = code;
  8313.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8314.         return(-1);
  8315.     }
  8316.     else {
  8317.     char tmp[BUFSIZ];
  8318.  
  8319.     if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
  8320.         !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
  8321.         timestamp_width = (int) strlen(tmp);
  8322.     else
  8323.         timestamp_width = 15;
  8324.     }
  8325.  
  8326.     if (mode == DEFAULT || mode == CCACHE)
  8327.      retval = do_ccache(kcontext,name);
  8328.     else
  8329.      retval = do_keytab(kcontext,name);
  8330.     krb5_free_context(kcontext);
  8331.     return(retval);
  8332. }
  8333.  
  8334. static int
  8335. #ifdef CK_ANSIC
  8336. do_keytab(krb5_context kcontext, char * name)
  8337. #else
  8338. do_keytab(kcontext,name) krb5_context kcontext; char * name;
  8339. #endif
  8340. {
  8341.     krb5_keytab kt;
  8342.     krb5_keytab_entry entry;
  8343.     krb5_kt_cursor cursor;
  8344.     char buf[BUFSIZ]; /* hopefully large enough for any type */
  8345.     char *pname;
  8346.     int code = 0;
  8347.  
  8348.     if (name == NULL) {
  8349.         if ((code = krb5_kt_default(kcontext, &kt))) {
  8350.             debug(F101,"ck_krb5_list_creds while getting default keytab",
  8351.                    "",code);
  8352.             krb5_errno = code;
  8353.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8354.             return(-1);
  8355.         }
  8356.     } else {
  8357.         if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
  8358.             debug(F111,"ck_krb5_list_creds while resolving keytab",
  8359.                      name,code);
  8360.             krb5_errno = code;
  8361.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8362.             return(-1);
  8363.         }
  8364.     }
  8365.  
  8366.     if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
  8367.         debug(F101,"ck_krb5_list_creds while getting keytab name",
  8368.                "",code);
  8369.         krb5_errno = code;
  8370.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8371.         return(-1);
  8372.     }
  8373.  
  8374.      printf("Keytab name: %s\r\n", buf);
  8375.  
  8376.      if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
  8377.          debug(F101,"ck_krb5_list_creds while starting keytab scan",
  8378.                 "",code);
  8379.          krb5_errno = code;
  8380.          makestr(&krb5_errmsg,error_message(krb5_errno));
  8381.          return(-1);
  8382.      }
  8383.  
  8384.      if (show_time) {
  8385.       printf("KVNO Timestamp");
  8386.           fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
  8387.       printf("Principal\r\n");
  8388.       printf("---- ");
  8389.       fillit(timestamp_width, (int) '-');
  8390.       printf(" ");
  8391.       fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
  8392.       printf("\r\n");
  8393.      } else {
  8394.       printf("KVNO Principal\r\n");
  8395.       printf(
  8396. "---- --------------------------------------------------------------------\
  8397. ------\r\n");
  8398.      }
  8399.  
  8400.     while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
  8401.         if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
  8402.             debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8403.                    "",code);
  8404.             krb5_errno = code;
  8405.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8406.             return(-1);
  8407.         }
  8408.         printf("%4d ", entry.vno);
  8409.         if (show_time) {
  8410.             printtime(entry.timestamp);
  8411.             printf(" ");
  8412.         }
  8413.         printf("%s", pname);
  8414.         if (show_etype)
  8415.             printf(" (%s) " ,
  8416. #ifdef HEIMDAL
  8417.                     etype_string(entry.key.keytype)
  8418. #else /* HEIMDAL */
  8419.                     etype_string(entry.key.enctype)
  8420. #endif /* HEIMDAL */
  8421.                     );
  8422.         if (show_keys) {
  8423.             printf(" (0x");
  8424.             {
  8425.                 int i;
  8426.                 for (i = 0; i < entry.key.length; i++)
  8427.                     printf("%02x",
  8428. #ifdef HEIMDAL
  8429.                             entry.key.keyvalue[i]
  8430. #else /* HEIMDAL */
  8431.                             entry.key.contents[i]
  8432. #endif /* HEIMDAL */
  8433.                             );
  8434.             }
  8435.             printf(")");
  8436.         }
  8437.         printf("\r\n");
  8438.         krb5_free_unparsed_name(kcontext,pname);
  8439.     }
  8440.     if (code && code != KRB5_KT_END) {
  8441.         debug(F101,"ck_krb5_list_creds while scanning keytab",
  8442.                "",code);
  8443.         krb5_errno = code;
  8444.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8445.         return(-1);
  8446.     }
  8447.     if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
  8448.         debug(F101,"ck_krb5_list_creds while ending keytab scan",
  8449.                "",code);
  8450.         krb5_errno = code;
  8451.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8452.         return(-1);
  8453.     }
  8454.     krb5_errno = 0;
  8455.     makestr(&krb5_errmsg,"OK");
  8456.     return(0);
  8457. }
  8458.  
  8459. static int
  8460. #ifdef CK_ANSIC
  8461. do_ccache(krb5_context kcontext, char * cc_name)
  8462. #else
  8463. do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
  8464. #endif
  8465. {
  8466.     krb5_ccache cache = NULL;
  8467.     krb5_cc_cursor cur;
  8468.     krb5_creds creds;
  8469.     krb5_principal princ=NULL;
  8470.     krb5_flags flags=0;
  8471.     krb5_error_code code = 0;
  8472.     int    exit_status = 0;
  8473.  
  8474.     if (status_only)
  8475.     /* exit_status is set back to 0 if a valid tgt is found */
  8476.     exit_status = 1;
  8477.  
  8478.     code = k5_get_ccache(kcontext,&cache,cc_name);
  8479.     if (code != 0) {
  8480.         debug(F111,"do_ccache while getting ccache",
  8481.                error_message(code),code);
  8482.         krb5_errno = code;
  8483.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8484.         return(-1);
  8485.     }
  8486.  
  8487.     flags = 0;                /* turns off OPENCLOSE mode */
  8488.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8489.     if (code == ENOENT) {
  8490.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  8491.                    krb5_cc_get_name(kcontext, cache),code);
  8492.     } else {
  8493.             debug(F111,
  8494.          "ck_krb5_list_creds while setting cache flags (ticket cache)",
  8495.                   krb5_cc_get_name(kcontext, cache),code);
  8496.     }
  8497.         printf("No ticket File.\r\n");
  8498.         krb5_errno = code;
  8499.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8500.         krb5_cc_close(kcontext,cache);
  8501.     return(-1);
  8502.     }
  8503.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  8504.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  8505.                "",code);
  8506.         krb5_errno = code;
  8507.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8508.         krb5_cc_close(kcontext,cache);
  8509.     return(-1);
  8510.     }
  8511.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  8512.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8513.                "",code);
  8514.         krb5_errno = code;
  8515.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8516.         krb5_cc_close(kcontext,cache);
  8517.     return(-1);
  8518.     }
  8519.     if (!status_only) {
  8520.     printf("Ticket cache:      %s:%s\r\nDefault principal: %s\r\n\r\n",
  8521.                 krb5_cc_get_type(kcontext, cache),
  8522.                 krb5_cc_get_name(kcontext, cache), defname);
  8523.     printf("Valid starting");
  8524.     fillit(timestamp_width - sizeof("Valid starting") + 3,
  8525.            (int) ' ');
  8526.     printf("Expires");
  8527.     fillit(timestamp_width - sizeof("Expires") + 3,
  8528.            (int) ' ');
  8529.     printf("Service principal\r\n");
  8530.     }
  8531.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  8532.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  8533.                "",code);
  8534.         krb5_errno = code;
  8535.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8536.         krb5_cc_close(kcontext,cache);
  8537.     return(-1);
  8538.     }
  8539.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  8540.     if (status_only) {
  8541.         if (exit_status && creds.server->length == 2 &&
  8542.         strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
  8543.         strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
  8544.         strcmp((char *)creds.server->data[1].data,
  8545.                princ->realm.data) == 0 &&
  8546.         creds.times.endtime > now)
  8547.         exit_status = 0;
  8548.     } else {
  8549.         show_credential(kcontext, &creds);
  8550.     }
  8551.     krb5_free_cred_contents(kcontext, &creds);
  8552.     }
  8553.     printf("\r\n");
  8554.     if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
  8555.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  8556.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  8557.                    "",code);
  8558.             krb5_errno = code;
  8559.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8560.             krb5_cc_close(kcontext,cache);
  8561.         return(-1);
  8562.     }
  8563.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  8564.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8565.             debug(F101,"ck_krb5_list_creds while closing ccache",
  8566.                    "",code);
  8567.             krb5_errno = code;
  8568.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8569.             krb5_cc_close(kcontext,cache);
  8570.         return(-1);
  8571.     }
  8572.         krb5_errno = 0;
  8573.         makestr(&krb5_errmsg,"OK");
  8574.         krb5_cc_close(kcontext,cache);
  8575.     return(0);
  8576.     } else {
  8577.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  8578.         krb5_errno = code;
  8579.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8580.         krb5_cc_close(kcontext,cache);
  8581.     return(-1);
  8582.     }
  8583.     krb5_errno = 0;
  8584.     makestr(&krb5_errmsg,"OK");
  8585.     krb5_cc_close(kcontext,cache);
  8586.     return(0);
  8587. }
  8588.  
  8589. static char *
  8590. #ifdef CK_ANSIC
  8591. #ifdef HEIMDAL
  8592. etype_string(krb5_keytype enctype)
  8593. #else /* HEIMDAL */
  8594. etype_string(krb5_enctype enctype)
  8595. #endif /* HEIMDAL */
  8596. #else
  8597. #ifdef HEIMDAL
  8598. etype_string(enctype) krb5_keytype enctype;
  8599. #else /* HEIMDAL */
  8600. etype_string(enctype) krb5_enctype enctype;
  8601. #endif /* HEIMDAL */
  8602. #endif
  8603. {
  8604.     static char buf[12];
  8605.  
  8606.     switch (enctype) {
  8607.     case ENCTYPE_NULL:
  8608.         return "NULL";
  8609.     case ENCTYPE_DES_CBC_CRC:
  8610.     return "DES-CBC-CRC";
  8611.     case ENCTYPE_DES_CBC_MD4:
  8612.     return "DES-CBC-MD4";
  8613.     case ENCTYPE_DES_CBC_MD5:
  8614.     return "DES-CBC-MD5";
  8615.     case ENCTYPE_DES_CBC_RAW:
  8616.         return "DES-CBC-RAW";
  8617.     case ENCTYPE_DES3_CBC_SHA:
  8618.     return "DES3-CBC-SHA";
  8619.     case ENCTYPE_DES3_CBC_RAW:
  8620.         return "DES3-CBC-RAW";
  8621.     case ENCTYPE_DES_HMAC_SHA1:
  8622.         return "DES-HMAC-SHA1";
  8623.     case ENCTYPE_DES3_CBC_SHA1:
  8624.         return "DES3-CBC-SHA1";
  8625.     case ENCTYPE_UNKNOWN:
  8626.         return "UNKNOWN";
  8627.     case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
  8628.         return "LOCAL-DES3-HMAC-SHA1";
  8629.     default:
  8630.     ckmakmsg(buf, sizeof(buf),"etype ", ckitoa(enctype),NULL,NULL);
  8631.     return buf;
  8632.     break;
  8633.     }
  8634. }
  8635.  
  8636. static char *
  8637. #ifdef CK_ANSIC
  8638. flags_string(register krb5_creds *cred)
  8639. #else
  8640. flags_string(cred) register krb5_creds *cred;
  8641. #endif
  8642. {
  8643.     static char buf[32];
  8644.     int i = 0;
  8645.  
  8646.     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
  8647.         buf[i++] = 'F';
  8648.     if (cred->ticket_flags & TKT_FLG_FORWARDED)
  8649.         buf[i++] = 'f';
  8650.     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
  8651.         buf[i++] = 'P';
  8652.     if (cred->ticket_flags & TKT_FLG_PROXY)
  8653.         buf[i++] = 'p';
  8654.     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
  8655.         buf[i++] = 'D';
  8656.     if (cred->ticket_flags & TKT_FLG_POSTDATED)
  8657.         buf[i++] = 'd';
  8658.     if (cred->ticket_flags & TKT_FLG_INVALID)
  8659.         buf[i++] = 'i';
  8660.     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
  8661.         buf[i++] = 'R';
  8662.     if (cred->ticket_flags & TKT_FLG_INITIAL)
  8663.         buf[i++] = 'I';
  8664.     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
  8665.         buf[i++] = 'H';
  8666.     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
  8667.         buf[i++] = 'A';
  8668.     buf[i] = '\0';
  8669.     return(buf);
  8670. }
  8671.  
  8672. static char   *
  8673. #ifdef CK_ANSIC
  8674. short_date(long   *dp)
  8675. #else
  8676. short_date(dp) long   *dp;
  8677. #endif
  8678. {
  8679.     register char *cp;
  8680. #ifndef ctime
  8681.     extern char *ctime();
  8682. #endif /* ctime */
  8683.     cp = ctime(dp) + 4;
  8684.     cp[15] = '\0';
  8685.     return (cp);
  8686. }
  8687.  
  8688.  
  8689. static VOID
  8690. #ifdef CK_ANSIC
  8691. printtime(time_t tv)
  8692. #else
  8693. printtime(tv) time_t tv;
  8694. #endif
  8695. {
  8696.     char timestring[BUFSIZ];
  8697.     char format[12];
  8698.     char fill;
  8699.  
  8700.     fill = ' ';
  8701.     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
  8702.     if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
  8703.                                      timestring,
  8704.                                      timestamp_width+1,
  8705.                      &fill)) {
  8706.         printf(format,timestring);
  8707.     }
  8708.     else {
  8709.         printf(format,short_date(&tv));
  8710.     }
  8711.  
  8712. }
  8713.  
  8714. static void
  8715. #ifdef CK_ANSIC
  8716. one_addr(krb5_address *a)
  8717. #else
  8718. one_addr(a) krb5_address *a;
  8719. #endif
  8720. {
  8721.     struct hostent *h;
  8722.     extern tcp_rdns;
  8723.  
  8724.     if ((a->addrtype == ADDRTYPE_INET) &&
  8725.         (a->length == 4)) {
  8726.         if (tcp_rdns != SET_OFF) {
  8727.             h = gethostbyaddr(a->contents, 4, AF_INET);
  8728.             if (h) {
  8729. #ifdef HADDRLIST
  8730.                 h = ck_copyhostent(h);
  8731. #endif /* HADDRLIST */
  8732.                 printf("%s (%d.%d.%d.%d)", h->h_name,
  8733.             a->contents[0], a->contents[1],
  8734.             a->contents[2], a->contents[3]);
  8735.             }
  8736.         }
  8737.         if (tcp_rdns == SET_OFF || !h) {
  8738.             printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
  8739.                    a->contents[2], a->contents[3]);
  8740.         }
  8741.     } else {
  8742.         printf("unknown addr type %d", a->addrtype);
  8743.     }
  8744. }
  8745.  
  8746. static VOID
  8747. #ifdef CK_ANSIC
  8748. show_credential(krb5_context kcontext, register krb5_creds * cred)
  8749. #else
  8750. show_credential(kcontext, cred)
  8751.     krb5_context        kcontext;
  8752.     register krb5_creds * cred;
  8753. #endif
  8754. {
  8755.     krb5_error_code retval=0;
  8756.     krb5_ticket *tkt=NULL;
  8757.     char *name=NULL, *sname=NULL, *flags=NULL;
  8758.     int    extra_field = 0;
  8759.  
  8760.     retval = krb5_unparse_name(kcontext, cred->client, &name);
  8761.     if (retval) {
  8762.     debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
  8763.         krb5_errno = retval;
  8764.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8765.     return;
  8766.     }
  8767.     retval = krb5_unparse_name(kcontext, cred->server, &sname);
  8768.     if (retval) {
  8769.     debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
  8770.     free(name);
  8771.         krb5_errno = retval;
  8772.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8773.     return;
  8774.     }
  8775.     if (!cred->times.starttime)
  8776.     cred->times.starttime = cred->times.authtime;
  8777.  
  8778.     printtime(cred->times.starttime);
  8779.     printf("  ");
  8780.  
  8781.     if ( time(0) < cred->times.endtime )
  8782.         printtime(cred->times.endtime);
  8783.     else
  8784.         printf("** expired ** ");
  8785.  
  8786.     printf("  %s\r\n", sname);
  8787.  
  8788.     if (strcmp(name, defname)) {
  8789.         printf("   for client %s", name);
  8790.         extra_field++;
  8791.     }
  8792.  
  8793.     if (cred->times.renew_till) {
  8794.     if (!extra_field)
  8795.             printf("   ");
  8796.     else
  8797.             printf(", ");
  8798.     printf("renew until ");
  8799.         printtime(cred->times.renew_till);
  8800.     extra_field += 2;
  8801.     }
  8802.  
  8803.     if (extra_field > 3) {
  8804.     printf("\r\n");
  8805.     extra_field = 0;
  8806.     }
  8807.  
  8808.     if (show_flags) {
  8809.     flags = flags_string(cred);
  8810.     if (flags && *flags) {
  8811.         if (!extra_field)
  8812.         printf("   ");
  8813.         else
  8814.         printf(", ");
  8815.         printf("Flags: %s", flags);
  8816.         extra_field++;
  8817.         }
  8818.     }
  8819.  
  8820.     if (extra_field > 2) {
  8821.     printf("\r\n");
  8822.     extra_field = 0;
  8823.     }
  8824.  
  8825.     if (show_etype) {
  8826.     retval = decode_krb5_ticket(&cred->ticket, &tkt);
  8827.     if (!extra_field)
  8828.         printf("   ");
  8829.     else
  8830.         printf(", ");
  8831. #ifdef HEIMDAL
  8832.     printf("Etype (skey, tkt): %s, %s ",
  8833.            etype_string(cred->session.keytype),
  8834.            etype_string(tkt->enc_part.keytype));
  8835. #else /* HEIMDAL */
  8836.     printf("Etype (skey, tkt): %s, %s ",
  8837.            etype_string(cred->keyblock.enctype),
  8838.            etype_string(tkt->enc_part.enctype));
  8839. #endif /* HEIMDAL */
  8840.     krb5_free_ticket(kcontext, tkt);
  8841.     extra_field++;
  8842.     }
  8843.  
  8844.     /* if any additional info was printed, extra_field is non-zero */
  8845.     if (extra_field)
  8846.     printf("\r\n");
  8847.  
  8848.     if ( show_addr ) {
  8849.         if (!cred->addresses || !cred->addresses[0]) {
  8850.             printf("\tAddresses: (none)\r\n");
  8851.         } else {
  8852.             int i;
  8853.             for (i=0; cred->addresses[i]; i++) {
  8854.         if (i)
  8855.             printf("              ");
  8856.         else
  8857.             printf("   Addresses: ");
  8858.                 one_addr(cred->addresses[i]);
  8859.         printf("\r\n");
  8860.             }
  8861.         }
  8862.     }
  8863.  
  8864.     krb5_free_unparsed_name(kcontext,name);
  8865.     krb5_free_unparsed_name(kcontext,sname);
  8866.  
  8867.     krb5_errno = 0;
  8868.     makestr(&krb5_errmsg,"OK");
  8869. }
  8870.  
  8871. static VOID
  8872. #ifdef CK_ANSIC
  8873. fillit(int num, int c)
  8874. #else
  8875. fillit(num, c) int num; int c;
  8876. #endif
  8877. {
  8878.     int i;
  8879.  
  8880.     for (i=0; i<num; i++)
  8881.     printf("%c",c);
  8882. }
  8883. #endif /* KLIST */
  8884. #endif /* KRB5 */
  8885.  
  8886. #ifdef KRB4
  8887. #define KDEBUG 1
  8888. int k4debug = 0;                /* Kerberos 4 runtime debugging */
  8889.  
  8890. #ifdef KINIT
  8891. #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
  8892.  
  8893. #ifdef SNK4
  8894. /* SNK4 is a hardware authentication system used to pre-authenticate    */
  8895. /* a ticket getting ticket.  We do not support this code at the present */
  8896. /* time in Kermit.                                                      */
  8897. void
  8898. get_input(s, size, stream)
  8899. char *s;
  8900. int size;
  8901. FILE *stream;
  8902. {
  8903.     char *p;
  8904.  
  8905.     if (fgets(s, size, stream) == NULL)
  8906.         exit(1);
  8907.     if ( (p = strchr(s, '\n')) != NULL)
  8908.         *p = '\0';
  8909. }
  8910. #endif /* SNK4 */
  8911.  
  8912. #ifdef COMMENT
  8913. static char
  8914. #ifdef CK_ANSIC
  8915. hex_scan_nybble(char c)
  8916. #else
  8917. hex_scan_nybble(c) char c;
  8918. #endif
  8919. {
  8920.     if (c >= '0' && c <= '9')
  8921.         return c - '0';
  8922.     if (c >= 'A' && c <= 'F')
  8923.         return c - 'A' + 10;
  8924.     if (c >= 'a' && c <= 'f')
  8925.         return c - 'a' + 10;
  8926.     return -1;
  8927. }
  8928.  
  8929. /* returns: NULL for ok, pointer to error string for bad input */
  8930. static char*
  8931. #ifdef CK_ANSIC
  8932. hex_scan_four_bytes(char *out, char *in)
  8933. #else
  8934. hex_scan_four_bytes(out, in) char *out; char *in;
  8935. #endif
  8936. {
  8937.     int i;
  8938.     int c;
  8939.     char c1;
  8940.     for (i=0; i<8; i++) {
  8941.         if(!in[i])
  8942.             return "not enough input";
  8943.         c = hex_scan_nybble(in[i]);
  8944.         if(c<0)
  8945.             return "invalid digit";
  8946.         c1 = c;
  8947.         i++;
  8948.         if(!in[i])
  8949.             return "not enough input";
  8950.         c = hex_scan_nybble(in[i]);
  8951.         if(c<0)
  8952.             return "invalid digit";
  8953.         *out++ = (c1 << 4) + c;
  8954.     }
  8955.     switch(in[i]) {
  8956.     case 0:
  8957.     case '\r':
  8958.     case '\n':
  8959.         return NULL;
  8960.     default:
  8961.         return "extra characters at end of input";
  8962.     }
  8963. }
  8964. #endif /* COMMENT */
  8965.  
  8966. /* ck_krb4_initTGT() returns 0 on success */
  8967. int
  8968. #ifdef CK_ANSIC
  8969. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  8970. #else
  8971. ck_krb4_initTGT(op,init)
  8972.     struct krb_op_data * op, struct krb4_init_data * init
  8973. #endif
  8974. {
  8975.     char    aname[ANAME_SZ+1];
  8976.     char    inst[INST_SZ+1];
  8977.     char    realm[REALM_SZ+1];
  8978.     char    *password=NULL;
  8979.     char    passwd[80]="";
  8980.     char    *username = NULL;
  8981.     char    *usernameptr=NULL;
  8982.     int     iflag,      /* Instance */
  8983.             rflag,      /* Realm */
  8984.             vflag,      /* Verbose */
  8985.             lflag,      /* Lifetime */
  8986.             pflag,      /* Preauth */
  8987.             lifetime=KRB_DEFAULT_LIFE,   /* Life Time */
  8988.             k_errno;
  8989.     register char *cp;
  8990.     register i;
  8991.  
  8992.     if ( !ck_krb4_is_installed() )
  8993.         return(-1);
  8994.  
  8995.     *inst = *realm = '\0';
  8996.     iflag = rflag = vflag = lflag = pflag = 0;
  8997.  
  8998.     vflag = init->verbose;
  8999.     pflag = init->preauth;
  9000.  
  9001.     if ( init->lifetime ) {
  9002.         lifetime = init->lifetime<5?1:init->lifetime/5;
  9003.         if ( lifetime > 255 ) lifetime = 255;
  9004.     }
  9005.     else
  9006.         lifetime = KRB_DEFAULT_LIFE;
  9007.  
  9008.     username = init->principal;
  9009.  
  9010.     if (username && username[0] &&
  9011.     (k_errno = kname_parse(aname, inst, realm, username))
  9012.     != AUTH_SUCCESS) {
  9013.         krb4_errno = k_errno;
  9014.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9015.     printf("%s\r\n", krb_get_err_text_entry(k_errno));
  9016.     iflag = rflag = 1;
  9017.     username = NULL;
  9018.     }
  9019.  
  9020.     if ( init->realm ) {
  9021.         ckstrncpy(realm,init->realm,REALM_SZ);
  9022.     }
  9023.  
  9024.     if ( init->instance ) {
  9025.         ckstrncpy(inst,init->instance, INST_SZ);
  9026.     }
  9027.  
  9028. #ifdef COMMENT
  9029.     if ( vflag )
  9030.         printf("Kerberos IV initialization\r\n");
  9031. #endif /* COMMENT */
  9032.  
  9033.     if (!username || !username[0]) {
  9034.         debug(F100,"ck_krb4_initTGT no username specified","",0);
  9035.         printf("?Invalid principal specified.\r\n");
  9036.         krb4_errno = -1;
  9037.         makestr(&krb4_errmsg,"No principal specified");
  9038.         return(-1);
  9039.     }
  9040.     if (!*realm) {
  9041.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
  9042.     }
  9043.  
  9044.     if ( init->password )
  9045.         password = init->password;
  9046.     else {
  9047.         char prmpt[80];
  9048.         ckmakxmsg(prmpt,sizeof(prmpt),
  9049.                   "Kerberos 4 Password for ",username,"@",realm,": ",
  9050.                    NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9051.         readpass(prmpt,passwd,80);
  9052.         password = passwd;
  9053.     }
  9054.  
  9055.     if (pflag) {
  9056.         k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
  9057.                                              "krbtgt", realm,
  9058.                                              lifetime,
  9059.                                              password);
  9060.     if (k_errno == -1) {    /* preauth method not available */
  9061.         k_errno = krb_get_pw_in_tkt(aname,
  9062.                      inst, realm,
  9063.                      "krbtgt", realm,
  9064.                      lifetime,
  9065.                      password);
  9066.     }
  9067.     } else {
  9068.         k_errno = krb_get_pw_in_tkt(aname,
  9069.                                      inst, realm,
  9070.                                      "krbtgt", realm,
  9071.                                      lifetime,
  9072.                                      password);
  9073.     }
  9074.  
  9075.     memset(passwd,0,sizeof(passwd));
  9076.     if (k_errno) {
  9077.         printf("%s for principal %s%s%s@%s\r\n",
  9078.         krb_get_err_text_entry(k_errno), aname,
  9079.                 inst[0]?".":"", inst, realm);
  9080.         krb4_errno = k_errno;
  9081.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9082.     return(-1);
  9083.     } else if (vflag) {
  9084.     printf("Result from realm %s: ", realm);
  9085.     printf("%s\r\n", krb_get_err_text_entry(k_errno));
  9086.     }
  9087.     krb4_errno = k_errno;
  9088.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9089.     return(0);
  9090. }
  9091. #endif /* KINIT */
  9092. #ifdef KDESTROY
  9093. int
  9094. #ifdef CK_ANSIC
  9095. ck_krb4_destroy(struct krb_op_data * op)
  9096. #else
  9097. ck_krb4_destroy(op) struct krb_op_data * op;
  9098. #endif
  9099. {
  9100.     int k_errno=0;
  9101.  
  9102.     if ( !ck_krb4_is_installed() )
  9103.         return(-1);
  9104.  
  9105.     k_errno = dest_tkt();
  9106.  
  9107.     krb4_errno = k_errno;
  9108.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9109.  
  9110.     if (k_errno == 0)
  9111.         printf("Tickets destroyed.\r\n");
  9112.     else if (k_errno == RET_TKFIL)
  9113.         printf("No tickets to destroy.\r\n");
  9114.     else {
  9115.         printf("Tickets MAY NOT be destroyed.\r\n");
  9116.         return(-1);
  9117.     }
  9118.     return(0);
  9119. }
  9120. #endif /* KDESTROY */
  9121. #ifdef KLIST
  9122. _PROTOTYP(static int display_tktfile,(char *, int, int, int));
  9123.  
  9124. int
  9125. #ifdef CK_ANSIC
  9126. ck_krb4_list_creds(struct krb_op_data * op)
  9127. #else
  9128. ck_krb4_list_creds(op) struct krb_op_data * op;
  9129. #endif
  9130. {
  9131.     int     long_form = 1;
  9132.     int     tgt_test = 0;
  9133.     int     do_srvtab = 0;
  9134.     int        show_kvnos = 0;
  9135.     char   *tkt_file = NULL;
  9136.  
  9137.     if ( !ck_krb4_is_installed() )
  9138.         return(-1);
  9139.  
  9140.     if ( op->cache )
  9141.         tkt_file = op->cache;
  9142.  
  9143.     if ( k4debug ) {
  9144.         show_kvnos = 1;
  9145.     }
  9146.  
  9147.     if (do_srvtab)
  9148.     return(display_srvtab(tkt_file));
  9149.     else
  9150.     return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
  9151. }
  9152.  
  9153. #ifndef KRB5
  9154. static int timestamp_width=0;
  9155.  
  9156. static char   *
  9157. #ifdef CK_ANSIC
  9158. short_date(long   *dp)
  9159. #else
  9160. short_date(dp) long   *dp;
  9161. #endif
  9162. {
  9163.     register char *cp;
  9164.     extern char *ctime();
  9165.     cp = ctime(dp) + 4;
  9166.     cp[15] = '\0';
  9167.     return (cp);
  9168. }
  9169.  
  9170.  
  9171. static VOID
  9172. #ifdef CK_ANSIC
  9173. printtime(time_t tv)
  9174. #else
  9175. printtime(tv) time_t tv;
  9176. #endif
  9177. {
  9178.     char timestring[BUFSIZ];
  9179.     char format[12];
  9180.     char fill;
  9181.  
  9182.     fill = ' ';
  9183.     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
  9184.     printf(format,short_date(&tv));
  9185. }
  9186. #endif /* KRB5 */
  9187.  
  9188. static int
  9189. #ifdef CK_ANSIC
  9190. display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
  9191. #else
  9192. display_tktfile(file,tgt_test,long_form,show_kvnos)
  9193.     char *file; int tgt_test; int long_form; int show_kvnos;
  9194. #endif
  9195. {
  9196.     char    pname[ANAME_SZ];
  9197.     char    pinst[INST_SZ];
  9198.     char    prealm[REALM_SZ];
  9199.     char    buf1[20], buf2[20];
  9200.     int     k_errno;
  9201. #ifdef OS2
  9202.     LEASH_CREDENTIALS creds;
  9203. #else /* OS2 */
  9204.     CREDENTIALS creds;
  9205. #endif /* OS2 */
  9206.     int     header = 1;
  9207.  
  9208.     file = tkt_string();
  9209.  
  9210.     if (long_form) {
  9211.     printf("Ticket cache:      %s\r\n", file);
  9212.     }
  9213.  
  9214.     /*
  9215.      * Since krb_get_tf_realm will return a ticket_file error,
  9216.      * we will call tf_init and tf_close first to filter out
  9217.      * things like no ticket file.  Otherwise, the error that
  9218.      * the user would see would be
  9219.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9220.      * instead of
  9221.      * klist: No ticket file (tf_util)
  9222.      */
  9223.  
  9224.     /* Open ticket file */
  9225.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9226.     if (!tgt_test)
  9227.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9228.         krb4_errno = k_errno;
  9229.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9230.         return(-1);
  9231.     }
  9232.  
  9233.  
  9234.     /* Close ticket file */
  9235.     (void) tf_close();
  9236.  
  9237.     /*
  9238.      * We must find the realm of the ticket file here before calling
  9239.      * tf_init because since the realm of the ticket file is not
  9240.      * really stored in the principal section of the file, the
  9241.      * routine we use must itself call tf_init and tf_close.
  9242.      */
  9243.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9244.     if (!tgt_test)
  9245.         printf("can't find realm of ticket file: %s\r\n",
  9246.             krb_get_err_text_entry (k_errno));
  9247.         krb4_errno = k_errno;
  9248.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9249.     return(-1);
  9250.     }
  9251.  
  9252.     /* Open ticket file */
  9253.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9254.     if (!tgt_test)
  9255.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9256.         krb4_errno = k_errno;
  9257.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9258.     return(-1);
  9259.     }
  9260.     /* Get principal name and instance */
  9261.     if ((k_errno = tf_get_pname(pname)) ||
  9262.          (k_errno = tf_get_pinst(pinst))) {
  9263.         (void) tf_close();
  9264.         if (!tgt_test)
  9265.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9266.         krb4_errno = k_errno;
  9267.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9268.         return(-1);
  9269.     }
  9270.  
  9271.     /*
  9272.      * You may think that this is the obvious place to get the
  9273.      * realm of the ticket file, but it can't be done here as the
  9274.      * routine to do this must open the ticket file.  This is why
  9275.      * it was done before tf_init.
  9276.      */
  9277.  
  9278.     if (!tgt_test && long_form)
  9279.     printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
  9280.            (pinst[0] ? "." : ""), pinst,
  9281.            (prealm[0] ? "@" : ""), prealm);
  9282.  
  9283.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9284.     if (!tgt_test && long_form && header) {
  9285.         printf("%-17s  %-17s  %s\r\n",
  9286.            "Valid starting", "Expires", "Service principal");
  9287.         header = 0;
  9288.     }
  9289.     if (tgt_test) {
  9290.         creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  9291.         if (!strcmp(creds.service, "krbtgt") &&
  9292.         !strcmp(creds.instance, prealm)) {
  9293.                 krb4_errno = k_errno;
  9294.                 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9295.  
  9296.                 (void) tf_close();
  9297.         if (time(0) < creds.issue_date) {
  9298.             return(0);        /* tgt hasn't expired */
  9299.         } else {
  9300.             return(-1);        /* has expired */
  9301.                 }
  9302.         }
  9303.         continue;            /* not a tgt */
  9304.     }
  9305.     if (long_form) {
  9306.             timestamp_width = 17;       /* for k5 display function */
  9307.                                         /* if available            */
  9308.             printtime(creds.issue_date);
  9309.             printf("  ");
  9310.         creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  9311.             if ( time(0) < creds.issue_date )
  9312.                 printtime(creds.issue_date);
  9313.             else
  9314.                 printf("*** expired ***  ");
  9315.             printf("  ");
  9316.     }
  9317.         if (show_kvnos)
  9318.       printf("%s%s%s%s%s (%d)\r\n",
  9319.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9320.          (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
  9321.     else
  9322.       printf("%s%s%s%s%s\r\n",
  9323.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9324.          (creds.realm[0] ? "@" : ""), creds.realm);
  9325.  
  9326. #ifdef OS2
  9327.     if ( creds.address[0] )
  9328.         printf("   Address: %s\r\n",creds.address);
  9329. #endif /* OS2 */
  9330.     }
  9331.  
  9332.     (void) tf_close();
  9333.  
  9334.     if (tgt_test) {
  9335.     return(-1);
  9336.     }/* no tgt found */
  9337.     if (header && long_form && k_errno == EOF) {
  9338.     printf("No tickets in file.\r\n");
  9339.     }
  9340.     krb4_errno = k_errno;
  9341.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9342.     return(0);
  9343. }
  9344.  
  9345. #ifdef COMMENT
  9346. /* Just so we remember what the command line interface looked like */
  9347. usage()
  9348. {
  9349.     printf(
  9350.     "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
  9351.     return(-1);
  9352. }
  9353. #endif /* COMMENT */
  9354.  
  9355. /* adapted from getst() in librkb */
  9356. /*
  9357.  * ok_getst() takes a file descriptor, a string and a count.  It reads
  9358.  * from the file until either it has read "count" characters, or until
  9359.  * it reads a null byte.  When finished, what has been read exists in
  9360.  * the given string "s".  If "count" characters were actually read, the
  9361.  * last is changed to a null, so the returned string is always null-
  9362.  * terminated.  ok_getst() returns the number of characters read, including
  9363.  * the null terminator.
  9364.  *
  9365.  * If there is a read error, it returns -1 (like the read(2) system call)
  9366.  */
  9367.  
  9368. static int
  9369. #ifdef CK_ANSIC
  9370. ok_getst(int fd, register char *s, int n)
  9371. #else
  9372. ok_getst(fd, s, n) int fd; register char *s; int n;
  9373. #endif
  9374. {
  9375.     register int count = n;
  9376.     int err;
  9377.     while ((err = read(fd, s, 1)) > 0 && --count)
  9378.         if (*s++ == '\0')
  9379.             return (n - count);
  9380.     if (err < 0)
  9381.     return(-1);
  9382.     *s = '\0';
  9383.     return (n - count);
  9384. }
  9385.  
  9386. int
  9387. #ifdef CK_ANSIC
  9388. display_srvtab(char *file)
  9389. #else
  9390. display_srvtab(file) char *file;
  9391. #endif
  9392. {
  9393.     int stab;
  9394.     char serv[SNAME_SZ];
  9395.     char inst[INST_SZ];
  9396.     char rlm[REALM_SZ];
  9397.     unsigned char key[8];
  9398.     unsigned char vno;
  9399.     int count;
  9400.  
  9401.     printf("Server key file:   %s\r\n", file);
  9402. #ifdef NT
  9403. #ifndef O_RDONLY
  9404. #define O_RDONLY _O_RDONLY
  9405. #endif /* O_RDONLY */
  9406. #endif /* NT */
  9407.  
  9408.     if ((stab = open(file, O_RDONLY, 0400)) < 0) {
  9409.     perror(file);
  9410.     return(-1);
  9411.     }
  9412.     printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
  9413.        "Key Version");
  9414.     printf("------------------------------------------------------\r\n");
  9415.  
  9416.     /* argh. getst doesn't return error codes, it silently fails */
  9417.     while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
  9418.        && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
  9419.        && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
  9420.     if (((count = read(stab,(char *) &vno,1)) != 1) ||
  9421.          ((count = read(stab,(char *) key,8)) != 8)) {
  9422.         if (count < 0)
  9423.         perror("reading from key file");
  9424.         else
  9425.         printf("key file truncated\r\n");
  9426.         return(-1);
  9427.     }
  9428.     printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
  9429.     }
  9430.     if (count < 0)
  9431.     perror(file);
  9432.     (void) close(stab);
  9433.     return(0);
  9434. }
  9435. #endif /* KLIST */
  9436. #else /* KRB4 */
  9437. int
  9438. ck_krb4_autoget_TGT(char * dummy)
  9439. {
  9440.     return(-1);
  9441. }
  9442. #ifdef CK_KERBEROS
  9443. int
  9444. #ifdef CK_ANSIC
  9445. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  9446. #else
  9447. ck_krb4_initTGT(op,init)
  9448.     struct krb_op_data * op, struct krb4_init_data * init
  9449. #endif
  9450. {
  9451.     return(-1);
  9452. }
  9453.  
  9454. #ifdef CK_ANSIC
  9455. ck_krb4_destroy(struct krb_op_data * op)
  9456. #else
  9457. ck_krb4_destroy(op) struct krb_op_data * op;
  9458. #endif
  9459. {
  9460.     return(-1);
  9461. }
  9462. int
  9463. #ifdef CK_ANSIC
  9464. ck_krb4_list_creds(struct krb_op_data * op)
  9465. #else
  9466. ck_krb4_list_creds(op) struct krb_op_data * op;
  9467. #endif
  9468. {
  9469.     return(-1);
  9470. }
  9471. #else /* CK_KERBEROS */
  9472. int ck_krb4_initTGT(void * a, void *b)
  9473. {
  9474.     return(-1);
  9475. }
  9476. int ck_krb4_destroy(void *a)
  9477. {
  9478.     return(-1);
  9479. }
  9480. int ck_krb4_list_creds(void *a)
  9481. {
  9482.     return(-1);
  9483. }
  9484. #endif /* CK_KERBEROS */
  9485. #endif /* KRB4 */
  9486.  
  9487. /* The following functions are used to implement the Kermit Script Language */
  9488. /* functions                                                                */
  9489.  
  9490. struct tkt_list_item {
  9491.     char * name;
  9492.     struct tkt_list_item * next;
  9493. };
  9494.  
  9495. static struct tkt_list_item * k4_tkt_list = NULL;
  9496.  
  9497. int
  9498. #ifdef CK_ANSIC
  9499. ck_krb4_get_tkts(VOID)
  9500. #else
  9501. ck_krb4_get_tkts()
  9502. #endif
  9503. {
  9504. #ifdef KRB4
  9505.     char   *file=NULL;
  9506.     char    pname[ANAME_SZ];
  9507.     char    pinst[INST_SZ];
  9508.     char    prealm[REALM_SZ];
  9509.     char    buf1[20], buf2[20];
  9510.     int     k_errno;
  9511. #ifdef OS2
  9512.     LEASH_CREDENTIALS creds;
  9513. #else /* OS2 */
  9514.     CREDENTIALS creds;
  9515. #endif /* OS2 */
  9516.     int     tkt_count=0;
  9517.     struct  tkt_list_item ** list = &k4_tkt_list;
  9518.  
  9519.     while ( k4_tkt_list ) {
  9520.         struct tkt_list_item * next;
  9521.         next = k4_tkt_list->next;
  9522.         free(k4_tkt_list->name);
  9523.         free(k4_tkt_list);
  9524.         k4_tkt_list = next;
  9525.     }
  9526.  
  9527.     if ( !ck_krb4_is_installed() )
  9528.         return(-1);
  9529.  
  9530.     file = tkt_string();
  9531.  
  9532.     /*
  9533.      * Since krb_get_tf_realm will return a ticket_file error,
  9534.      * we will call tf_init and tf_close first to filter out
  9535.      * things like no ticket file.  Otherwise, the error that
  9536.      * the user would see would be
  9537.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9538.      * instead of
  9539.      * klist: No ticket file (tf_util)
  9540.      */
  9541.  
  9542.     /* Open ticket file */
  9543.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9544.         return(-1);
  9545.     }
  9546.  
  9547.     /* Close ticket file */
  9548.     (void) tf_close();
  9549.  
  9550.     /*
  9551.      * We must find the realm of the ticket file here before calling
  9552.      * tf_init because since the realm of the ticket file is not
  9553.      * really stored in the principal section of the file, the
  9554.      * routine we use must itself call tf_init and tf_close.
  9555.      */
  9556.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9557.     return(-1);
  9558.     }
  9559.  
  9560.     /* Open ticket file */
  9561.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9562.     return(-1);
  9563.     }
  9564.     /* Get principal name and instance */
  9565.     if ((k_errno = tf_get_pname(pname)) ||
  9566.          (k_errno = tf_get_pinst(pinst))) {
  9567.         return(-1);
  9568.     }
  9569.  
  9570.     /*
  9571.      * You may think that this is the obvious place to get the
  9572.      * realm of the ticket file, but it can't be done here as the
  9573.      * routine to do this must open the ticket file.  This is why
  9574.      * it was done before tf_init.
  9575.      */
  9576.  
  9577.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9578.         char tkt_buf[256];
  9579.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9580.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9581.          (creds.realm[0] ? "@" : ""), creds.realm,
  9582.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9583.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  9584.         (*list)->name = strdup(tkt_buf);
  9585.         (*list)->next = NULL;
  9586.         list = &((*list)->next);
  9587.         tkt_count++;
  9588.     }
  9589.  
  9590.     tf_close();
  9591.     return(tkt_count);
  9592. #else /* KRB4 */
  9593.     return(0);
  9594. #endif /* KRB4 */
  9595. }
  9596.  
  9597. char *
  9598. #ifdef CK_ANSIC
  9599. ck_krb4_get_next_tkt(VOID)
  9600. #else
  9601. ck_krb4_get_next_tkt()
  9602. #endif
  9603. {
  9604. #ifdef KRB4
  9605.     static char * s=NULL;
  9606.     struct tkt_list_item * next=NULL;
  9607.  
  9608.     if ( s ) {
  9609.         free(s);
  9610.         s = NULL;
  9611.     }
  9612.  
  9613.     if ( k4_tkt_list == NULL )
  9614.         return(NULL);
  9615.  
  9616.     next = k4_tkt_list->next;
  9617.     s = k4_tkt_list->name;
  9618.     free(k4_tkt_list);
  9619.     k4_tkt_list = next;
  9620.     return(s);
  9621. #else /* KRB4 */
  9622.     return(NULL);
  9623. #endif /* KRB4 */
  9624. }
  9625.  
  9626. int
  9627. #ifdef CK_ANSIC
  9628. ck_krb4_tkt_isvalid(char * tktname)
  9629. #else
  9630. ck_krb4_tkt_isvalid(tktname) char * tktname;
  9631. #endif
  9632. {
  9633. #ifdef KRB4
  9634.     char   *file=NULL;
  9635.     char    pname[ANAME_SZ];
  9636.     char    pinst[INST_SZ];
  9637.     char    prealm[REALM_SZ];
  9638.     char    buf1[20], buf2[20];
  9639.     int     k_errno;
  9640.     time_t  issue_t, expire_t, now_t;
  9641. #ifdef OS2
  9642.     LEASH_CREDENTIALS creds;
  9643. #else /* OS2 */
  9644.     CREDENTIALS creds;
  9645. #endif /* OS2 */
  9646.  
  9647.     if ( !ck_krb4_is_installed() )
  9648.         return(-1);
  9649.  
  9650.     debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
  9651.     file = tkt_string();
  9652.  
  9653.     /*
  9654.      * Since krb_get_tf_realm will return a ticket_file error,
  9655.      * we will call tf_init and tf_close first to filter out
  9656.      * things like no ticket file.  Otherwise, the error that
  9657.      * the user would see would be
  9658.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9659.      * instead of
  9660.      * klist: No ticket file (tf_util)
  9661.      */
  9662.  
  9663.     /* Open ticket file */
  9664.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  9665.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9666.         return(-1);
  9667.     }
  9668.  
  9669.     /* Close ticket file */
  9670.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9671.     (void) tf_close();
  9672.  
  9673.     /*
  9674.      * We must find the realm of the ticket file here before calling
  9675.      * tf_init because since the realm of the ticket file is not
  9676.      * really stored in the principal section of the file, the
  9677.      * routine we use must itself call tf_init and tf_close.
  9678.      */
  9679.     debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
  9680.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9681.     return(-1);
  9682.     }
  9683.  
  9684.     /* Open ticket file */
  9685.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  9686.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9687.     return(-1);
  9688.     }
  9689.     /* Get principal name and instance */
  9690.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
  9691.     if ((k_errno = tf_get_pname(pname)) ||
  9692.          (k_errno = tf_get_pinst(pinst))) {
  9693.  
  9694.         /* Close ticket file */
  9695.         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9696.         (void) tf_close();
  9697.  
  9698.         return(-1);
  9699.     }
  9700.  
  9701.     /*
  9702.      * You may think that this is the obvious place to get the
  9703.      * realm of the ticket file, but it can't be done here as the
  9704.      * routine to do this must open the ticket file.  This is why
  9705.      * it was done before tf_init.
  9706.      */
  9707.  
  9708.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
  9709.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9710.         char tkt_buf[256];
  9711.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9712.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9713.          (creds.realm[0] ? "@" : ""), creds.realm,
  9714.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9715.         if ( !strcmp(tktname,tkt_buf) ) {
  9716.  
  9717.             /* we found the ticket we are looking for */
  9718.             issue_t = creds.issue_date;
  9719.             expire_t = creds.issue_date
  9720.                 + ((unsigned char) creds.lifetime) * 5 * 60;
  9721.             now_t = time(0);
  9722.  
  9723.             /* We add a 5 minutes fudge factor to compensate for potential */
  9724.             /* clock skew errors between the KDC and K95's host OS         */
  9725.  
  9726.             if ( now_t >= (issue_t-300) && now_t < expire_t) {
  9727. #ifdef OS2
  9728. #ifdef CHECKADDRS
  9729.         if ( krb4_checkaddrs ) {
  9730.             extern char myipaddr[20];       /* From ckcnet.c */
  9731.             if ( !myipaddr[0] ) {
  9732.             int i;
  9733.             char buf[60];
  9734.             for ( i=0;i<64;i++ ) {
  9735.                 if ( getlocalipaddrs(buf,60,i) < 0 )
  9736.                 break;
  9737.  
  9738.                 if ( !strcmp(buf,creds.address) ) {
  9739.                 /* Close ticket file */
  9740.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9741.                 (void) tf_close();
  9742.                 return(1); /* They're the same */
  9743.                 }
  9744.             }
  9745.  
  9746.             /* Close ticket file */
  9747.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9748.             (void) tf_close();
  9749.             return(0);                  /* They're different */
  9750.             } else if ( strcmp(myipaddr,creds.address) ) {
  9751.             /* Close ticket file */
  9752.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9753.             (void) tf_close();
  9754.             return(0);                  /* They're different */
  9755.             }
  9756.             else {
  9757.             /* Close ticket file */
  9758.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9759.             (void) tf_close();
  9760.             return(1);                  /* They're the same */
  9761.             }
  9762.         } else {
  9763.             /* Close ticket file */
  9764.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9765.             (void) tf_close();
  9766.             return(1);                  /* They're the same */
  9767.         }
  9768. #else /* CHECKADDRS */
  9769.                 /* Close ticket file */
  9770.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9771.                 (void) tf_close();
  9772.                 return(1);      /* valid but no ip address check */
  9773. #endif /* CHECKADDRS */
  9774. #else /* OS2 */
  9775.                 /* Close ticket file */
  9776.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9777.                 (void) tf_close();
  9778.                 return(1);      /* Valid but no ip address check */
  9779. #endif /* OS2 */
  9780.             }
  9781.             else {
  9782.                 /* Close ticket file */
  9783.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9784.                 (void) tf_close();
  9785.                 return(0);      /* expired or otherwise invalid */
  9786.             }
  9787.         }
  9788.     }
  9789.     /* Close ticket file */
  9790.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9791.     (void) tf_close();
  9792.     return(0);                  /* could not find the desired ticket */
  9793. #else /* KRB4 */
  9794.     return(-1);
  9795. #endif /* KRB4 */
  9796. }
  9797.  
  9798. int
  9799. #ifdef CK_ANSIC
  9800. ck_krb4_is_tgt_valid(VOID)
  9801. #else
  9802. ck_krb4_is_tgt_valid()
  9803. #endif
  9804. {
  9805. #ifdef KRB4
  9806.     char tgt[256];
  9807.     char * s;
  9808.     int rc = 0;
  9809.  
  9810.     s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
  9811.     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",s,"@",s);
  9812.     rc = ck_krb4_tkt_isvalid(tgt);
  9813.     debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
  9814.     return(rc > 0);
  9815. #else /* KRB4 */
  9816.     return(0);
  9817. #endif /* KRB4 */
  9818. }
  9819.  
  9820. int
  9821. #ifdef CK_ANSIC
  9822. ck_krb4_tkt_time(char * tktname)
  9823. #else
  9824. ck_krb4_tkt_time(tktname) char * tktname;
  9825. #endif
  9826. {
  9827. #ifdef KRB4
  9828.     char   *file=NULL;
  9829.     char    pname[ANAME_SZ];
  9830.     char    pinst[INST_SZ];
  9831.     char    prealm[REALM_SZ];
  9832.     char    buf1[20], buf2[20];
  9833.     int     k_errno;
  9834. #ifdef OS2
  9835.     LEASH_CREDENTIALS creds;
  9836. #else /* OS2 */
  9837.     CREDENTIALS creds;
  9838. #endif /* OS2 */
  9839.  
  9840.     if ( !ck_krb4_is_installed() )
  9841.         return(-1);
  9842.  
  9843.     file = tkt_string();
  9844.  
  9845.     /*
  9846.      * Since krb_get_tf_realm will return a ticket_file error,
  9847.      * we will call tf_init and tf_close first to filter out
  9848.      * things like no ticket file.  Otherwise, the error that
  9849.      * the user would see would be
  9850.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9851.      * instead of
  9852.      * klist: No ticket file (tf_util)
  9853.      */
  9854.  
  9855.     /* Open ticket file */
  9856.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9857.         return(-1);
  9858.     }
  9859.  
  9860.     /* Close ticket file */
  9861.     (void) tf_close();
  9862.  
  9863.     /*
  9864.      * We must find the realm of the ticket file here before calling
  9865.      * tf_init because since the realm of the ticket file is not
  9866.      * really stored in the principal section of the file, the
  9867.      * routine we use must itself call tf_init and tf_close.
  9868.      */
  9869.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9870.     return(-1);
  9871.     }
  9872.  
  9873.     /* Open ticket file */
  9874.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9875.     return(-1);
  9876.     }
  9877.     /* Get principal name and instance */
  9878.     if ((k_errno = tf_get_pname(pname)) ||
  9879.          (k_errno = tf_get_pinst(pinst))) {
  9880.         tf_close();
  9881.         return(-1);
  9882.     }
  9883.  
  9884.     /*
  9885.      * You may think that this is the obvious place to get the
  9886.      * realm of the ticket file, but it can't be done here as the
  9887.      * routine to do this must open the ticket file.  This is why
  9888.      * it was done before tf_init.
  9889.      */
  9890.  
  9891.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9892.         char tkt_buf[256];
  9893.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9894.          creds.service, (creds.instance[0] ? "." : ""),
  9895.                  creds.instance,
  9896.          (creds.realm[0] ? "@" : ""), creds.realm,
  9897.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9898.         if ( !strcmp(tktname,tkt_buf) ) {
  9899.             /* we found the ticket we are looking for */
  9900.             int n = (creds.issue_date
  9901.                       + (((unsigned char) creds.lifetime) * 5 * 60))
  9902.                 - time(0);
  9903.             tf_close();
  9904.             return(n <= 0 ? 0 : n);
  9905.         }
  9906.     }
  9907.     tf_close();
  9908.     return(0);                  /* could not find the desired ticket */
  9909. #else /* KRB4 */
  9910.     return(-1);
  9911. #endif /* KRB4 */
  9912. }
  9913.  
  9914. char *
  9915. #ifdef CK_ANSIC
  9916. ck_krb4_getrealm(void)
  9917. #else
  9918. ck_krb4_getrealm()
  9919. #endif
  9920. {
  9921. #ifdef KRB4
  9922.     char   *file=NULL;
  9923.     int     k_errno;
  9924.     static char realm[256]="";
  9925.     realm[0]='\0';
  9926.  
  9927.     if ( !ck_krb4_is_installed() )
  9928.         return(realm);
  9929.  
  9930.     /* Try to get realm from ticket file */
  9931.     /* If failure get the local realm    */
  9932.  
  9933.     /*
  9934.     * Since krb_get_tf_realm will return a ticket_file error,
  9935.     * we will call tf_init and tf_close first to filter out
  9936.     * things like no ticket file.
  9937.     */
  9938.  
  9939.     /* Open ticket file */
  9940.     file = tkt_string();
  9941.     if (file == NULL || !file[0])
  9942.         return(realm);
  9943.  
  9944.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  9945.         /* Close ticket file */
  9946.         (void) tf_close();
  9947.  
  9948.         k_errno = krb_get_tf_realm(file, realm);
  9949.     }
  9950.     if (k_errno != KSUCCESS) {
  9951.         k_errno = krb_get_lrealm(realm, 1);
  9952.     }
  9953.     return(realm);
  9954. #else /* KRB4 */
  9955.     return("");
  9956. #endif /* KRB4 */
  9957. }
  9958.  
  9959. char *
  9960. #ifdef CK_ANSIC
  9961. ck_krb4_getprincipal(void)
  9962. #else
  9963. ck_krb4_getprincipal()
  9964. #endif
  9965. {
  9966. #ifdef KRB4
  9967.     char   *file=NULL;
  9968.     int     k_errno;
  9969.     static char principal[256]="";
  9970.     char        instance[256]="";
  9971.     char        realm[256]="";
  9972.     principal[0]='\0';
  9973.  
  9974.     if ( !ck_krb4_is_installed() )
  9975.         return(principal);
  9976.  
  9977.     /* Try to get realm from ticket file */
  9978.     /* If failure get the local realm    */
  9979.  
  9980.     /*
  9981.     * Since krb_get_tf_realm will return a ticket_file error,
  9982.     * we will call tf_init and tf_close first to filter out
  9983.     * things like no ticket file.
  9984.     */
  9985.  
  9986.     /* Open ticket file */
  9987.     file = tkt_string();
  9988.     if (file == NULL || !file[0])
  9989.         return(principal);
  9990.  
  9991.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  9992.         /* Close ticket file */
  9993.         (void) tf_close();
  9994.  
  9995.         k_errno = krb_get_tf_fullname(file, principal, instance, realm);
  9996.     }
  9997.     return(principal);
  9998. #else /* KRB4 */
  9999.     return("");
  10000. #endif /* KRB4 */
  10001. }
  10002.  
  10003. static struct tkt_list_item * k5_tkt_list = NULL;
  10004.  
  10005. int
  10006. #ifdef CK_ANSIC
  10007. ck_krb5_get_tkts(char * cc_name)
  10008. #else
  10009. ck_krb5_get_tkts(cc_name) char * cc_name;
  10010. #endif
  10011. {
  10012. #ifdef KRB5
  10013. #ifndef HEIMDAL
  10014.     krb5_context kcontext;
  10015.     krb5_error_code retval;
  10016.     krb5_ccache cache = NULL;
  10017.     krb5_cc_cursor cur;
  10018.     krb5_creds creds;
  10019.     krb5_principal princ=NULL;
  10020.     krb5_flags flags=0;
  10021.     krb5_error_code code=0;
  10022.     int    exit_status = 0;
  10023.  
  10024.     int     tkt_count=0;
  10025.     struct  tkt_list_item ** list = &k5_tkt_list;
  10026.  
  10027.     while ( k5_tkt_list ) {
  10028.         struct tkt_list_item * next;
  10029.         next = k5_tkt_list->next;
  10030.         free(k5_tkt_list->name);
  10031.         free(k5_tkt_list);
  10032.         k5_tkt_list = next;
  10033.     }
  10034.  
  10035.     if ( !ck_krb5_is_installed() )
  10036.         return(-1);
  10037.  
  10038.     retval = krb5_init_context(&kcontext);
  10039.     if (retval) {
  10040.         debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
  10041.         return(-1);
  10042.     }
  10043.  
  10044.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10045.     if (code != 0) {
  10046.         debug(F111,"ck_krb5_get_tkts while getting ccache",
  10047.                error_message(code),code);
  10048.         tkt_count = -1;
  10049.         goto exit_k5_get_tkt;
  10050.     }
  10051.  
  10052.     flags = 0;                /* turns off OPENCLOSE mode */
  10053.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10054.     if (code == ENOENT) {
  10055.             debug(F111,"ck_krb5_get_tkts (ticket cache)",
  10056.                    krb5_cc_get_name(kcontext, cache),code);
  10057.     } else {
  10058.             debug(F111,
  10059.          "ck_krb5_get_tkts while setting cache flags (ticket cache)",
  10060.                   krb5_cc_get_name(kcontext, cache),code);
  10061.     }
  10062.         tkt_count = -1;
  10063.         goto exit_k5_get_tkt;
  10064.     }
  10065.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10066.         debug(F101,"ck_krb5_get_tkts while retrieving principal name",
  10067.                "",code);
  10068.         tkt_count = -1;
  10069.         goto exit_k5_get_tkt;
  10070.     }
  10071.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10072.         debug(F101,"ck_krb5_get_tkts while unparsing principal name",
  10073.                "",code);
  10074.         tkt_count = -1;
  10075.         goto exit_k5_get_tkt;
  10076.     }
  10077.  
  10078.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10079.         debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
  10080.                "",code);
  10081.         tkt_count = -1;
  10082.         goto exit_k5_get_tkt;
  10083.     }
  10084.  
  10085.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10086.         char *sname=NULL;
  10087.  
  10088.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10089.         if (retval) {
  10090.             debug(F101,
  10091.           "ck_krb5_get_tkts while unparsing server name","",retval);
  10092.             tkt_count = -1;
  10093.             goto exit_k5_get_tkt;
  10094.         }
  10095.  
  10096.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  10097.         (*list)->name = sname;
  10098.         (*list)->next = NULL;
  10099.         list = &((*list)->next);
  10100.  
  10101.     krb5_free_cred_contents(kcontext, &creds);
  10102.         tkt_count++;
  10103.     }
  10104.  
  10105.     if (code == KRB5_CC_END) {
  10106.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10107.             debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
  10108.                    "",code);
  10109.             tkt_count = -1;
  10110.             goto exit_k5_get_tkt;
  10111.     }
  10112.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  10113.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10114.             debug(F101,"ck_krb5_get_tkts while closing ccache",
  10115.                    "",code);
  10116.             tkt_count = -1;
  10117.             goto exit_k5_get_tkt;
  10118.     }
  10119.     } else {
  10120.         debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
  10121.         tkt_count = -1;
  10122.         goto exit_k5_get_tkt;
  10123.     }
  10124.  
  10125.   exit_k5_get_tkt:
  10126.     krb5_free_principal(kcontext,princ);
  10127.     krb5_free_unparsed_name(kcontext,defname);
  10128.     krb5_cc_close(kcontext,cache);
  10129.     krb5_free_context(kcontext);
  10130.     return(tkt_count);
  10131. #else /* HEIMDAL */
  10132.     return(-1);
  10133. #endif /* HEIMDAL */
  10134. #else /* KRB5 */
  10135.     return(0);
  10136. #endif /* KRB5 */
  10137. }
  10138.  
  10139. char *
  10140. #ifdef CK_ANSIC
  10141. ck_krb5_get_next_tkt(VOID)
  10142. #else
  10143. ck_krb5_get_next_tkt()
  10144. #endif
  10145. {
  10146. #ifdef KRB5
  10147. #ifndef HEIMDAL
  10148.     static char * s=NULL;
  10149.     struct tkt_list_item * next=NULL;
  10150.  
  10151.     if ( s ) {
  10152.         free(s);
  10153.         s = NULL;
  10154.     }
  10155.  
  10156.     if ( k5_tkt_list == NULL )
  10157.         return(NULL);
  10158.  
  10159.     next = k5_tkt_list->next;
  10160.     s = k5_tkt_list->name;
  10161.     free(k5_tkt_list);
  10162.     k5_tkt_list = next;
  10163.     return(s);
  10164. #else /* HEIMDAL */
  10165.     return("Not implemented");
  10166. #endif /* HEIMDAL */
  10167. #else /* KRB5 */
  10168.     return(NULL);
  10169. #endif /* KRB5 */
  10170. }
  10171.  
  10172. char *
  10173. #ifdef CK_ANSIC
  10174. ck_krb5_tkt_flags(char * cc_name, char * tktname)
  10175. #else
  10176. ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
  10177. #endif
  10178. {
  10179. #ifdef KRB5
  10180. #ifndef HEIMDAL
  10181.     krb5_context kcontext;
  10182.     krb5_error_code retval;
  10183.     krb5_ccache cache = NULL;
  10184.     krb5_cc_cursor cur;
  10185.     krb5_creds creds;
  10186.     krb5_principal princ=NULL;
  10187.     krb5_flags flags=0;
  10188.     krb5_error_code code=0;
  10189.     char * flag_str = "";
  10190.  
  10191.     if ( !ck_krb5_is_installed() )
  10192.         return("");
  10193.  
  10194.     retval = krb5_init_context(&kcontext);
  10195.     if (retval) {
  10196.         debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
  10197.         return("");
  10198.     }
  10199.  
  10200.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10201.     if (code != 0) {
  10202.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  10203.                error_message(code),code);
  10204.         goto exit_k5_get_tkt;
  10205.     }
  10206.  
  10207.     flags = 0;                /* turns off OPENCLOSE mode */
  10208.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10209.     if (code == ENOENT) {
  10210.             debug(F111,"ck_krb5_tkt_flags (ticket cache)",
  10211.                    krb5_cc_get_name(kcontext, cache),code);
  10212.     } else {
  10213.             debug(F111,
  10214.          "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
  10215.                   krb5_cc_get_name(kcontext, cache),code);
  10216.     }
  10217.         retval = -1;
  10218.         goto exit_k5_get_tkt;
  10219.     }
  10220.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10221.         debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
  10222.                "",code);
  10223.         retval = -1;
  10224.         goto exit_k5_get_tkt;
  10225.     }
  10226.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10227.         debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
  10228.                "",code);
  10229.         retval = -1;
  10230.         goto exit_k5_get_tkt;
  10231.     }
  10232.  
  10233.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10234.         debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
  10235.                "",code);
  10236.         retval = -1;
  10237.         goto exit_k5_get_tkt;
  10238.     }
  10239.  
  10240.     if ((code = krb5_timeofday(kcontext, &now))) {
  10241.         if (!status_only)
  10242.             debug(F101,"ck_krb5_tkt_flags while getting time of day.",
  10243.                    "",code);
  10244.         retval = -1;
  10245.         goto exit_k5_get_tkt;
  10246.     }
  10247.  
  10248.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10249.         char *sname=NULL;
  10250.  
  10251.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10252.         if (retval) {
  10253.             debug(F101,
  10254.           "ck_krb5_tkt_flags while unparsing server name","",retval);
  10255.             retval = -1;
  10256.             krb5_free_cred_contents(kcontext, &creds);
  10257.             goto exit_k5_get_tkt;
  10258.         }
  10259.  
  10260.         if ( !strcmp(sname,tktname) ) {
  10261.             /* we found the ticket we are looking for */
  10262.  
  10263.             flag_str = flags_string(&creds);
  10264.  
  10265.             krb5_free_cred_contents(kcontext, &creds);
  10266.             code = KRB5_CC_END;
  10267.             break;
  10268.         }
  10269.     krb5_free_cred_contents(kcontext, &creds);
  10270.     }
  10271.  
  10272.     if (code == KRB5_CC_END) {
  10273.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10274.             debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
  10275.                    "",code);
  10276.             goto exit_k5_get_tkt;
  10277.     }
  10278.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  10279.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10280.             debug(F101,"ck_krb5_tkt_flags while closing ccache",
  10281.                    "",code);
  10282.             goto exit_k5_get_tkt;
  10283.     }
  10284.     } else {
  10285.         debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
  10286.         goto exit_k5_get_tkt;
  10287.     }
  10288.  
  10289.   exit_k5_get_tkt:
  10290.     krb5_free_principal(kcontext,princ);
  10291.     krb5_free_unparsed_name(kcontext,defname);
  10292.     krb5_cc_close(kcontext,cache);
  10293.     krb5_free_context(kcontext);
  10294.     return(flag_str);
  10295. #else /* HEIMDAL */
  10296.     return("Not implemented");
  10297. #endif /* HEIMDAL */
  10298. #else /* KRB5 */
  10299.     return("");
  10300. #endif /* KRB5 */
  10301. }
  10302.  
  10303.  
  10304. int
  10305. #ifdef CK_ANSIC
  10306. ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
  10307. #else
  10308. ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
  10309. #endif
  10310. {
  10311. #ifdef KRB5
  10312. #ifndef HEIMDAL
  10313.     krb5_context kcontext=NULL;
  10314.     krb5_error_code retval;
  10315.     krb5_ccache cache = NULL;
  10316.     krb5_cc_cursor cur;
  10317.     krb5_creds creds;
  10318.     krb5_principal princ=NULL;
  10319.     krb5_flags flags=0;
  10320.     krb5_error_code code=0;
  10321. #ifdef CHECKADDRS
  10322.     krb5_address **    myAddrs=NULL;
  10323.     krb5_address **    p=NULL;
  10324.     BOOL            Addrfound = FALSE;
  10325. #endif /*CHECKADDRS*/
  10326.  
  10327.     if ( !ck_krb5_is_installed() )
  10328.         return(-1);
  10329.  
  10330.     retval = krb5_init_context(&kcontext);
  10331.     if (retval) {
  10332.         debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
  10333.         return(-1);
  10334.     }
  10335.  
  10336.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10337.     if (code != 0) {
  10338.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  10339.                error_message(code),code);
  10340.         goto exit_k5_get_tkt;
  10341.     }
  10342.  
  10343.     flags = 0;                /* turns off OPENCLOSE mode */
  10344.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10345.     if (code == ENOENT) {
  10346.             debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
  10347.                    krb5_cc_get_name(kcontext, cache),code);
  10348.     } else {
  10349.             debug(F111,
  10350.         "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
  10351.                   krb5_cc_get_name(kcontext, cache),code);
  10352.     }
  10353.         retval = -1;
  10354.         goto exit_k5_get_tkt;
  10355.     }
  10356.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10357.         debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
  10358.                "",code);
  10359.         retval = -1;
  10360.         goto exit_k5_get_tkt;
  10361.     }
  10362.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10363.         debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
  10364.                "",code);
  10365.         retval = -1;
  10366.         goto exit_k5_get_tkt;
  10367.     }
  10368.  
  10369.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10370.         debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
  10371.                "",code);
  10372.         retval = -1;
  10373.         goto exit_k5_get_tkt;
  10374.     }
  10375.  
  10376.     if ((code = krb5_timeofday(kcontext, &now))) {
  10377.         if (!status_only)
  10378.             debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
  10379.                    "",code);
  10380.         retval = -1;
  10381.         goto exit_k5_get_tkt;
  10382.     }
  10383.  
  10384.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10385.         char *sname=NULL;
  10386.  
  10387.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10388.         if (retval) {
  10389.             debug(F101,
  10390.           "ck_krb5_tkt_isvalid while unparsing server name","",retval);
  10391.             retval = -1;
  10392.             krb5_free_cred_contents(kcontext, &creds);
  10393.             goto exit_k5_get_tkt;
  10394.         }
  10395.  
  10396.         if ( !strcmp(sname,tktname) ) {
  10397.             /* we found the ticket we are looking for */
  10398.  
  10399.             /* We add a 5 minutes fudge factor to compensate for potential */
  10400.             /* clock skew errors between the KDC and K95's host OS         */
  10401.  
  10402.             retval = ((creds.times.starttime > 0) &&
  10403.                        now >= (creds.times.starttime - 300) &&
  10404.                        now < (creds.times.endtime + 300) &&
  10405.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  10406.  
  10407. #ifdef CHECKADDRS
  10408.             if ( retval && krb5_checkaddrs &&
  10409.                  creds.addresses && creds.addresses[0] ) {
  10410.                 /* if we think it is valid, then lets check the IP Addresses */
  10411.                 /* to make sure it is valid for our current connection.      */
  10412.                 /* Also make sure it's for the correct IP address */
  10413.         retval = krb5_os_localaddr(kcontext, &myAddrs);
  10414.                 if (retval) {
  10415.                     com_err(NULL, retval, "retrieving my IP address");
  10416.                     krb5_free_cred_contents(kcontext, &creds);
  10417.                     code = KRB5_CC_END;
  10418.                     retval = -1;
  10419.                     break;
  10420.                 }
  10421.  
  10422.          /* See if any of our addresses match any in cached credentials */
  10423.  
  10424.                 for (Addrfound=FALSE, p=myAddrs;
  10425.              (Addrfound==FALSE) && (*p);
  10426.              p++
  10427.              ) {
  10428.                     if (krb5_address_search(kcontext, *p, creds.addresses)) {
  10429.             Addrfound = TRUE;
  10430.                     }
  10431.                 }
  10432.                 krb5_free_addresses(k5_context, myAddrs);
  10433.  
  10434.                 if (Addrfound) {
  10435.                     krb5_free_cred_contents(kcontext, &creds);
  10436.                     code = KRB5_CC_END;
  10437.                     retval = 1;
  10438.                     break;
  10439.                 } else {
  10440.                     krb5_free_cred_contents(kcontext, &creds);
  10441.                     code = KRB5_CC_END;
  10442.                     retval = 0;
  10443.                     break;
  10444.                 }
  10445.             }
  10446. #endif /* CHECKADDRS */
  10447.  
  10448.             krb5_free_cred_contents(kcontext, &creds);
  10449.             code = KRB5_CC_END;
  10450.             break;
  10451.         }
  10452.     krb5_free_cred_contents(kcontext, &creds);
  10453.     }
  10454.  
  10455.     if (code == KRB5_CC_END) {
  10456.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10457.             debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
  10458.                    "",code);
  10459.             retval = -1;
  10460.             goto exit_k5_get_tkt;
  10461.     }
  10462.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  10463.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10464.             debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
  10465.                    "",code);
  10466.             retval = -1;
  10467.             goto exit_k5_get_tkt;
  10468.     }
  10469.     } else {
  10470.         debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
  10471.         retval = -1;
  10472.         goto exit_k5_get_tkt;
  10473.     }
  10474.  
  10475.   exit_k5_get_tkt:
  10476.     krb5_free_principal(kcontext,princ);
  10477.     krb5_free_unparsed_name(kcontext,defname);
  10478.     krb5_cc_close(kcontext,cache);
  10479.     krb5_free_context(kcontext);
  10480.     return(retval);
  10481. #else /* HEIMDAL */
  10482.     return(-1);
  10483. #endif /* HEIMDAL */
  10484. #else /* KRB5 */
  10485.     return(-1);
  10486. #endif /* KRB5 */
  10487. }
  10488.  
  10489. int
  10490. #ifdef CK_ANSIC
  10491. ck_krb5_is_tgt_valid(VOID)
  10492. #else
  10493. ck_krb5_is_tgt_valid()
  10494. #endif
  10495. {
  10496. #ifdef KRB5
  10497. #ifndef HEIMDAL
  10498.     char tgt[256];
  10499.     char * s;
  10500.     int rc = 0;
  10501.  
  10502.     s = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  10503.     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",s,"@",s);
  10504.     rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
  10505.     debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
  10506.     return(rc>0);
  10507. #else /* HEIMDAL */
  10508.     return(-1);
  10509. #endif /* HEIMDAL */
  10510. #else /* KRB5 */
  10511.     return(0);
  10512. #endif /* KRB5 */
  10513. }
  10514.  
  10515. int
  10516. #ifdef CK_ANSIC
  10517. ck_krb5_tkt_time(char * cc_name, char * tktname)
  10518. #else
  10519. ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
  10520. #endif
  10521. {
  10522. #ifdef KRB5
  10523. #ifndef HEIMDAL
  10524.     krb5_context kcontext;
  10525.     krb5_error_code retval;
  10526.     krb5_ccache cache = NULL;
  10527.     krb5_cc_cursor cur;
  10528.     krb5_creds creds;
  10529.     krb5_principal princ=NULL;
  10530.     krb5_flags flags=0;
  10531.     krb5_error_code code=0;
  10532.  
  10533.     if ( !ck_krb5_is_installed() )
  10534.         return(-1);
  10535.  
  10536.     retval = krb5_init_context(&kcontext);
  10537.     if (retval) {
  10538.         debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
  10539.         return(-1);
  10540.     }
  10541.  
  10542.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10543.     if (code != 0) {
  10544.         debug(F111,"ck_krb5_tkt_time while getting ccache",
  10545.                error_message(code),code);
  10546.         retval = -1;
  10547.         goto exit_k5_get_tkt;
  10548.     }
  10549.  
  10550.     flags = 0;                /* turns off OPENCLOSE mode */
  10551.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10552.     if (code == ENOENT) {
  10553.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  10554.                    krb5_cc_get_name(kcontext, cache),code);
  10555.     } else {
  10556.             debug(F111,
  10557.          "ck_krb5_list_creds while setting cache flags (ticket cache)",
  10558.                   krb5_cc_get_name(kcontext, cache),code);
  10559.     }
  10560.         retval = -1;
  10561.         goto exit_k5_get_tkt;
  10562.     }
  10563.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10564.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  10565.                "",code);
  10566.         retval = -1;
  10567.         goto exit_k5_get_tkt;
  10568.     }
  10569.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10570.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  10571.                "",code);
  10572.         retval = -1;
  10573.         goto exit_k5_get_tkt;
  10574.     }
  10575.  
  10576.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10577.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  10578.                "",code);
  10579.         retval = -1;
  10580.         goto exit_k5_get_tkt;
  10581.     }
  10582.  
  10583.     if ((code = krb5_timeofday(kcontext, &now))) {
  10584.         if (!status_only)
  10585.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  10586.                    "",code);
  10587.         krb5_free_context(kcontext);
  10588.         return(-1);
  10589.     }
  10590.  
  10591.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10592.         char *sname=NULL;
  10593.  
  10594.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10595.         if (retval) {
  10596.             debug(F101,
  10597.           "ck_krb5_list_creds while unparsing server name","",retval);
  10598.             retval = -1;
  10599.             krb5_free_cred_contents(kcontext, &creds);
  10600.             goto exit_k5_get_tkt;
  10601.         }
  10602.  
  10603.         if ( !strcmp(sname,tktname) ) {
  10604.             /* we found the ticket we are looking for */
  10605.             int valid = (creds.times.starttime &&
  10606.                        now > creds.times.starttime &&
  10607.                        now < creds.times.endtime &&
  10608.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  10609.             if ( valid ) {
  10610.                 retval = creds.times.endtime - now;
  10611.             }
  10612.             else
  10613.                 retval = 0;
  10614.             krb5_free_cred_contents(kcontext, &creds);
  10615.             code = KRB5_CC_END;
  10616.             break;
  10617.         }
  10618.     krb5_free_cred_contents(kcontext, &creds);
  10619.     }
  10620.  
  10621.     if (code == KRB5_CC_END) {
  10622.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10623.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  10624.                    "",code);
  10625.             retval = -1;
  10626.             goto exit_k5_get_tkt;
  10627.     }
  10628.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  10629.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10630.             debug(F101,"ck_krb5_list_creds while closing ccache",
  10631.                    "",code);
  10632.             retval = -1;
  10633.             goto exit_k5_get_tkt;
  10634.     }
  10635.     } else {
  10636.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  10637.         retval = -1;
  10638.         goto exit_k5_get_tkt;
  10639.     }
  10640.  
  10641.   exit_k5_get_tkt:
  10642.     krb5_free_principal(kcontext,princ);
  10643.     krb5_free_unparsed_name(kcontext,defname);
  10644.     krb5_cc_close(kcontext,cache);
  10645.     krb5_free_context(kcontext);
  10646.     return(retval);
  10647. #else /* HEIMDAL */
  10648.     return(-1);
  10649. #endif /* HEIMDAL */
  10650. #else /* KRB5 */
  10651.     return(-1);
  10652. #endif /* KRB5 */
  10653. }
  10654.  
  10655. char *
  10656. #ifdef CK_ANSIC
  10657. ck_krb5_get_cc_name(void)
  10658. #else
  10659. ck_krb5_get_cc_name()
  10660. #endif
  10661. {
  10662. #ifdef KRB5
  10663. #ifndef HEIMDAL
  10664.     static char cc_name[CKMAXPATH+1]="";
  10665.     krb5_context kcontext = NULL;
  10666.     krb5_ccache ccache = NULL;
  10667.     krb5_error_code code;
  10668.     char * p=NULL;
  10669.  
  10670.     cc_name[0] = '\0';
  10671.  
  10672.     if ( !ck_krb5_is_installed() )
  10673.         return(cc_name);
  10674.  
  10675.     p = getenv("KRB5CCNAME");
  10676.     if ( !p ) {
  10677.         code = krb5_init_context(&kcontext);
  10678.         if (code) {
  10679.             com_err("ck_krb5_get_cc_name",code,"while init_context");
  10680.             return(cc_name);
  10681.         }
  10682.         if ((code = krb5_cc_default(kcontext, &ccache))) {
  10683.             com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
  10684.             goto exit_k5_get_cc;
  10685.         }
  10686.  
  10687.         ckmakmsg(cc_name,sizeof(cc_name),krb5_cc_get_type(kcontext,ccache),":",
  10688.                  krb5_cc_get_name(kcontext,ccache),NULL);
  10689.     } else {
  10690.         ckstrncpy(cc_name,p,CKMAXPATH);
  10691.     }
  10692.  
  10693.     if ( !strncmp("FILE:",cc_name,5) ) {
  10694.         for ( p=cc_name; *p ; p++ )
  10695.             if ( *p == '\\' ) *p = '/';
  10696.     }
  10697.  
  10698.   exit_k5_get_cc:
  10699.     if ( ccache )
  10700.         krb5_cc_close(kcontext,ccache);
  10701.     if ( kcontext )
  10702.         krb5_free_context(kcontext);
  10703.     return(cc_name);
  10704. #else /* HEIMDAL */
  10705.     return("Not implemented");
  10706. #endif /* HEIMDAL */
  10707. #else /* KRB5 */
  10708.     return("");
  10709. #endif /* KRB5 */
  10710. }
  10711.  
  10712. char *
  10713. #ifdef CK_ANSIC
  10714. ck_krb5_getrealm(char * cc_name)
  10715. #else
  10716. ck_krb5_getrealm(cc_name) char * cc_name;
  10717. #endif
  10718. {
  10719. #ifdef KRB5
  10720. #ifndef HEIMDAL
  10721.     static char realm[256]="";
  10722.     krb5_context kcontext;
  10723.     krb5_ccache ccache = NULL;
  10724.     krb5_error_code code;
  10725.     krb5_principal me;
  10726.  
  10727.     realm[0] = '\0';
  10728.  
  10729.     if ( !ck_krb5_is_installed() )
  10730.         return(realm);
  10731.  
  10732.     code = krb5_init_context(&kcontext);
  10733.     if (code) {
  10734.         return(realm);
  10735.     }
  10736.  
  10737.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  10738.     if (code != 0) {
  10739.         goto exit_k5_getrealm;
  10740.     }
  10741.  
  10742.     if ((code = krb5_parse_name(kcontext, "foo", &me))) {
  10743.         goto exit_k5_getrealm;
  10744.     }
  10745.     if ( krb5_princ_realm(kcontext, me)->length < sizeof(realm) ) {
  10746.         memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  10747.                 krb5_princ_realm(kcontext, me)->length);        /* safe */
  10748.        realm[krb5_princ_realm(kcontext, me)->length]='\0';
  10749.     }
  10750.   exit_k5_getrealm:
  10751.     if ( ccache )
  10752.         krb5_cc_close(kcontext,ccache);
  10753.     if (kcontext)
  10754.         krb5_free_context(kcontext);
  10755.     return(realm);
  10756. #else /* HEIMDAL */
  10757.     return("Not implemented");
  10758. #endif /* HEIMDAL */
  10759. #else /* KRB5 */
  10760.     return("");
  10761. #endif /* KRB5 */
  10762. }
  10763.  
  10764. char *
  10765. #ifdef CK_ANSIC
  10766. ck_krb5_getprincipal(char * cc_name)
  10767. #else
  10768. ck_krb5_getprincipal(cc_name) char * cc_name;
  10769. #endif
  10770. {
  10771. #ifdef KRB5
  10772. #ifndef HEIMDAL
  10773.     static char principal[UIDBUFLEN+1]="";
  10774.     krb5_context kcontext;
  10775.     krb5_ccache ccache = NULL;
  10776.     krb5_error_code code;
  10777.     krb5_principal me;
  10778.     char * p=NULL;
  10779.     int i;
  10780.  
  10781.     principal[0] = '\0';
  10782.  
  10783.     if ( !ck_krb5_is_installed() )
  10784.         return(principal);
  10785.  
  10786.     code = krb5_init_context(&kcontext);
  10787.     if (code) {
  10788.         return(principal);
  10789.     }
  10790.  
  10791.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  10792.     if (code != 0) {
  10793.         goto exit_k5_getprincipal;
  10794.     }
  10795.  
  10796.     if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
  10797.         goto exit_k5_getprincipal;
  10798.     }
  10799.  
  10800.     if ((code = krb5_unparse_name (kcontext, me, &p))) {
  10801.         krb5_free_principal(kcontext,me);
  10802.         goto exit_k5_getprincipal;
  10803.     }
  10804.  
  10805.     ckstrncpy(principal,p,UIDBUFLEN);
  10806.     i = ckindex("@",principal,0,0,0);
  10807.     if (i)
  10808.       principal[i-1] = '\0';
  10809.  
  10810.     krb5_free_unparsed_name(kcontext,p);
  10811.  
  10812.   exit_k5_getprincipal:
  10813.     if ( ccache )
  10814.         krb5_cc_close(kcontext,ccache);
  10815.     if (kcontext)
  10816.         krb5_free_context(kcontext);
  10817.     return(principal);
  10818. #else /* HEIMDAL */
  10819.     return("Not implemented");
  10820. #endif /* HEIMDAL */
  10821. #else /* KRB5 */
  10822.     return("");
  10823. #endif /* KRB5 */
  10824. }
  10825.  
  10826. #ifndef CRYPT_DLL
  10827. int
  10828. ck_get_crypt_table(struct keytab ** pTable, int * pN)
  10829. {
  10830. #ifdef CK_ENCRYPTION
  10831.     return(get_crypt_table(pTable, pN));
  10832. #else /* ENCRYPTION */
  10833.     int i=0;
  10834. #ifndef OS2
  10835.     char * tmpstring = NULL;
  10836. #endif /* OS2 */
  10837.  
  10838.     if ( *pTable )
  10839.     {
  10840.         for ( i=0 ; i < *pN ; i++ )
  10841.             free( (*pTable)[i].kwd ) ;
  10842.         free ( *pTable )  ;
  10843.     }
  10844.     *pTable = NULL;
  10845.     *pN = 0;
  10846.  
  10847.     *pTable = malloc( sizeof(struct keytab) * 2 ) ;
  10848.     if ( !(*pTable) )
  10849.         return(0);
  10850.  
  10851. #ifdef OS2
  10852.     (*pTable)[0].kwd =strdup("automatic");
  10853. #else /* OS2 */
  10854.     makestr(&tmpstring,"automatic");
  10855.     (*pTable)[0].kwd = tmpstring;
  10856.     tmpstring = NULL;
  10857. #endif /* OS2 */
  10858.     (*pTable)[0].kwval = ENCTYPE_ANY;
  10859.     (*pTable)[0].flgs = 0;
  10860. #ifdef OS2
  10861.     (*pTable)[1].kwd =strdup("none");
  10862. #else /* OS2 */
  10863.     makestr(&tmpstring,"none");
  10864.     (*pTable)[1].kwd = tmpstring;
  10865.     tmpstring = NULL;
  10866. #endif /* OS2 */
  10867.     (*pTable)[1].kwval = 999;
  10868.     (*pTable)[1].flgs = 0;
  10869.     (*pN) = 2;
  10870.  
  10871.     return(2);
  10872. #endif /* ENCRYPTION */
  10873. }
  10874.  
  10875. VOID
  10876. ck_encrypt_send_support()
  10877. {
  10878. #ifdef CK_ENCRYPTION
  10879.     encrypt_send_support();
  10880. #endif /* ENCRYPTION */
  10881. }
  10882. #endif /* CRYPT_DLL */
  10883.  
  10884. /*
  10885.  *
  10886.  * Kstream
  10887.  *
  10888.  * Emulates the kstream package in Kerberos 4
  10889.  *
  10890.  */
  10891.  
  10892. int
  10893. kstream_destroy()
  10894. {
  10895.     if (g_kstream != NULL) {
  10896.         auth_destroy();                       /* Destroy authorizing */
  10897.         free(g_kstream);
  10898.         g_kstream=NULL;
  10899.     }
  10900.     return 0;
  10901. }
  10902.  
  10903. VOID
  10904. #ifdef CK_ANSIC
  10905. kstream_set_buffer_mode(int mode)
  10906. #else
  10907. kstream_set_buffer_mode(mode) int mode;
  10908. #endif
  10909. {
  10910. }
  10911.  
  10912.  
  10913. int
  10914. #ifdef CK_ANSIC
  10915. kstream_create_from_fd(int fd,
  10916.                const struct kstream_crypt_ctl_block *ctl,
  10917.                kstream_ptr data)
  10918. #else
  10919. kstream_create_from_fd(fd,ctl,data)
  10920.     int fd; const struct kstream_crypt_ctl_block *ctl; kstream_ptr data;
  10921. #endif
  10922. {
  10923.     int n;
  10924.  
  10925.     g_kstream = malloc(sizeof(struct kstream_int));
  10926.     if (g_kstream == NULL)
  10927.         return 0;
  10928.  
  10929.     g_kstream->fd = fd;
  10930.  
  10931.     n = auth_init(g_kstream);                   /* Initialize authorizing */
  10932.     if (n) {
  10933.         free(g_kstream);
  10934.         g_kstream = NULL;
  10935.         return 0;
  10936.     }
  10937.  
  10938.     g_kstream->encrypt = NULL;
  10939.     g_kstream->decrypt = NULL;
  10940.     g_kstream->encrypt_type = ENCTYPE_ANY;
  10941.     g_kstream->decrypt_type = ENCTYPE_ANY;
  10942.     return 1;
  10943. }
  10944.  
  10945. #ifdef CK_KERBEROS
  10946. #ifdef RLOGCODE
  10947. #ifdef MIT_CURRENT
  10948. static int do_lencheck, do_inband;
  10949.  
  10950. void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client)
  10951.      krb5_keyblock *in_keyblock;
  10952.      int encrypt_flag;
  10953.      int lencheck;
  10954.      int am_client;
  10955. {
  10956.     krb5_error_code status;
  10957.     size_t blocksize;
  10958.     krb5_boolean similar;
  10959.  
  10960.     if (!encrypt_flag)
  10961.     return;
  10962.  
  10963.     desinbuf.data = des_inbuf;
  10964.     desoutbuf.data = des_outpkt+4;    /* Set up des buffers */
  10965.     k5_session_key = in_keyblock;
  10966.  
  10967.     do_lencheck = lencheck;
  10968.  
  10969.     if (status = krb5_c_enctype_compare(k5_context, ENCTYPE_DES_CBC_CRC,
  10970.                     k5_session_key->enctype,
  10971.                     &similar)) {
  10972.     /* XXX what do I do? */
  10973.     return;
  10974.     }
  10975.  
  10976.     if (similar) {
  10977.     encivec_i.length = encivec_o.length = 0;
  10978.     return;
  10979.     }
  10980.  
  10981.     if (status = krb5_c_block_size(k5_context, k5_session_key->enctype,
  10982.                    &blocksize)) {
  10983.     /* XXX what do I do? */
  10984.     return;
  10985.     }
  10986.  
  10987.     encivec_i.length = encivec_o.length = blocksize;
  10988.  
  10989.     if ((encivec_i.data = malloc(encivec_i.length * 2)) == NULL) {
  10990.     /* XXX what do I do? */
  10991.     return;
  10992.     }
  10993.     encivec_o.data = encivec_i.data + encivec_i.length;
  10994.  
  10995.     /* is there a better way to initialize this? */
  10996.     memset(encivec_i.data, am_client, blocksize);
  10997.     memset(encivec_o.data, 1 - am_client, blocksize);
  10998. }
  10999. #endif /* MIT_CURRENT */
  11000.  
  11001.  
  11002. int
  11003. #ifdef CK_ANSIC
  11004. ck_krb_rlogin(CHAR * hostname, int port,
  11005.                CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
  11006.                struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
  11007.                int kversion, int encrypt_flag)
  11008. #else /* CK_ANSIC */
  11009. ck_krb_rlogin(hostname, port,
  11010.                localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
  11011.     CHAR * hostname; int port;
  11012.     CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
  11013.     struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
  11014.     int kversion; int encrypt_flag;
  11015. #endif /* CK_ANSIC */
  11016. {
  11017.     unsigned long status;
  11018.     char * realm=NULL;
  11019.     extern int ttyfd;
  11020.     int c;
  11021.     long msglen;
  11022.  
  11023.     debug(F111,"ck_krb_rlogin",hostname,port);
  11024.  
  11025.     if ( kversion == 4 && !ck_krb4_is_installed() ) {
  11026.         printf("?Kerberos 4 is not installed\r\n");
  11027.         return(-1);
  11028.     } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
  11029.         printf("?Kerberos 5 is not installed\r\n");
  11030.         return(-1);
  11031.     }
  11032.  
  11033.     if ( encrypt_flag && !ck_crypt_is_installed() ) {
  11034.         printf("?Encryption is not installed\r\n");
  11035.         return(-1);
  11036.     }
  11037.  
  11038.     if ( kversion == 5 ) {
  11039. #ifdef KRB5
  11040.         krb5_flags authopts=0;
  11041.         krb5_ccache ccache=NULL;
  11042.         char *cksumbuf=NULL;
  11043.         char *service=NULL;
  11044.         krb5_data cksumdat;
  11045.         krb5_creds *get_cred = 0;
  11046.         krb5_error_code status;
  11047.         krb5_error    *error = 0;
  11048.         krb5_ap_rep_enc_part *rep_ret = NULL;
  11049.         krb5_data outbuf;
  11050.         int rc;
  11051.         krb5_int32 seqno=0;
  11052.         krb5_int32 server_seqno=0;
  11053.         char ** realmlist=NULL;
  11054.     int buflen;
  11055.  
  11056.         debug(F100,"ck_krb_rlogin version 5","",0);
  11057.  
  11058.     buflen = strlen(term_speed)+strlen(remoteuser)+64;
  11059.         if ((cksumbuf = malloc(buflen)) == 0)
  11060.       {
  11061.           printf("Unable to allocate memory for checksum buffer.\r\n");
  11062.           return(-1);
  11063.       }
  11064.  
  11065.         ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),
  11066.                   term_speed,remoteuser,NULL);
  11067.         cksumdat.data = cksumbuf;
  11068.         cksumdat.length = strlen(cksumbuf);
  11069.  
  11070.         status = krb5_init_context(&k5_context);
  11071.         if (status) {
  11072.             debug(F110,"ck_krb_rlogin()","unable to init_context",0);
  11073.             return(-1);
  11074.         }
  11075.  
  11076.         desinbuf.data = des_inbuf;
  11077.         desoutbuf.data = des_outpkt+4;    /* Set up des buffers */
  11078.  
  11079.         rc = k5_get_ccache(k5_context,&ccache,NULL);
  11080.         if (rc != 0) {
  11081.             com_err(NULL, rc, "while getting ccache.");
  11082.             return(0);
  11083.         }
  11084.  
  11085.         service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
  11086.  
  11087.         if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
  11088.             printf("ck_krb_rlogin: no memory\r\n");
  11089.             return(-1);
  11090.         }
  11091.         status = krb5_sname_to_principal(k5_context, hostname, service,
  11092.                                           KRB5_NT_SRV_HST, &get_cred->server);
  11093.         if (status) {
  11094.         printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
  11095.                      error_message(status));
  11096.         return(-1);
  11097.         }
  11098.  
  11099.         krb5_get_host_realm(k5_context,hostname,&realmlist);
  11100.         if (realmlist && realmlist[0]) {
  11101.             makestr(&realm,realmlist[0]);
  11102.             krb5_free_host_realm(k5_context,realmlist);
  11103.             realmlist = NULL;
  11104.         }
  11105.         if (!realm || !realm[0] )
  11106.             realm = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  11107.         if (realm && *realm) {
  11108.             free(krb5_princ_realm(k5_context,get_cred->server)->data);
  11109.             krb5_princ_set_realm_length(k5_context,
  11110.                     get_cred->server,
  11111.                     strlen(realm)
  11112.                     );
  11113.             krb5_princ_set_realm_data(k5_context,
  11114.                       get_cred->server,
  11115.                       strdup(realm)
  11116.                       );
  11117.         }
  11118.  
  11119.         ttoc(0);
  11120.  
  11121.         if (status = krb5_cc_get_principal(k5_context,
  11122.                        ccache,
  11123.                        &get_cred->client)
  11124.         ) {
  11125.             (void) krb5_cc_close(k5_context, ccache);
  11126.             krb5_free_creds(k5_context, get_cred);
  11127.             goto bad2;
  11128.         }
  11129.  
  11130.         /* Get ticket from credentials cache or kdc */
  11131.         status = krb5_get_credentials(k5_context,
  11132.                       0,
  11133.                       ccache,
  11134.                       get_cred,
  11135.                       &ret_cred
  11136.                       );
  11137.         krb5_free_creds(k5_context, get_cred);
  11138.         get_cred = NULL;
  11139.         (void) krb5_cc_close(k5_context, ccache);
  11140.  
  11141.         if (status)
  11142.             goto bad2;
  11143.  
  11144.         authopts = AP_OPTS_MUTUAL_REQUIRED;
  11145. #ifdef MIT_CURRENT
  11146.     {
  11147.             krb5_boolean similar;
  11148.  
  11149.             if (status = krb5_c_enctype_compare( k5_context,
  11150.                                                  ENCTYPE_DES_CBC_CRC,
  11151. #ifdef HEIMDAL
  11152.                                                  ret_cred->session.keytype,
  11153. #else /* HEIMDAL */
  11154.                                                  ret_cred->keyblock.enctype,
  11155. #endif /* HEIMDAL */
  11156.                                                  &similar)) {
  11157.                 krb5_free_creds(k5_context, ret_cred);
  11158.                 ret_cred = NULL;
  11159.                 return(-1);
  11160.             }
  11161.         if ( !similar )
  11162.         authopts |= AP_OPTS_USE_SUBKEY;
  11163.     }
  11164. #endif /* MIT_CURRENT */
  11165.  
  11166.         if (krb5_auth_con_init(k5_context, &auth_context))
  11167.             goto bad2;
  11168.  
  11169.         if (krb5_auth_con_setflags(k5_context, auth_context,
  11170.                                     KRB5_AUTH_CONTEXT_RET_TIME))
  11171.             goto bad2;
  11172.  
  11173.         /* Only need local address for mk_cred() to send to krlogind */
  11174.         if (!krb5_d_no_addresses)
  11175.           if (status = krb5_auth_con_genaddrs(k5_context,
  11176.                         auth_context,
  11177.                         ttyfd,
  11178.                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
  11179.                         )
  11180.         )
  11181.             goto bad2;
  11182.  
  11183.         /* call Kerberos library routine to obtain an authenticator,
  11184.            pass it over the socket to the server, and obtain mutual
  11185.            authentication.
  11186.          */
  11187.         status = krb5_sendauth(k5_context,
  11188.                    &auth_context,
  11189.                    (krb5_pointer) &ttyfd,
  11190.                    "KCMDV0.1",
  11191.                    ret_cred->client,
  11192.                    ret_cred->server,
  11193.                                 authopts,
  11194.                    &cksumdat,
  11195.                    ret_cred,
  11196.                    0,
  11197.                    &error,
  11198.                    &rep_ret,
  11199.                    NULL
  11200.                    );
  11201.         krb5_free_data_contents(k5_context,&cksumdat);
  11202.  
  11203.         if (status) {
  11204.         printf("Couldn't authenticate to server: %s\r\n",
  11205.                      error_message(status));
  11206.             if (error) {
  11207.                 printf("Server returned error code %d (%s)\r\n",
  11208.                         error->error,
  11209.                         error_message(ERROR_TABLE_BASE_krb5 + error->error));
  11210.                 if (error->text.length) {
  11211.                     printf("Error text sent from server: %s\r\n",
  11212.                              error->text.data);
  11213.                 }
  11214.                 krb5_free_error(k5_context, error);
  11215.                 error = 0;
  11216.             }
  11217.             goto bad2;
  11218.         }
  11219.  
  11220.         if (rep_ret) {
  11221.             server_seqno = rep_ret->seq_number;
  11222.             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
  11223.         }
  11224.  
  11225.         (void) ttol(remoteuser, strlen(remoteuser)+1);
  11226.         (void) ttol(term_speed, strlen(term_speed)+1);
  11227.         (void) ttol(localuser, strlen(localuser)+1);
  11228.  
  11229.         if (forward_flag) {   /* Forward credentials (global) */
  11230.             if (status = krb5_fwd_tgt_creds( k5_context,
  11231.                                              auth_context,
  11232.                                              hostname,
  11233.                                              ret_cred->client,
  11234.                                              ret_cred->server,
  11235.                                              0,
  11236.                                              (forwardable_flag ?
  11237.                                                OPTS_FORWARDABLE_CREDS :
  11238.                                                0),
  11239.                                              &outbuf
  11240.                                              )
  11241.                  )
  11242.             {
  11243.                 printf("Error forwarding credentials: %s\r\n",
  11244.                          error_message(status));
  11245.                 goto bad2;
  11246.             }
  11247.  
  11248.             /* Send forwarded credentials */
  11249. #ifndef COMMENT
  11250.             if (status = krb5_write_message(k5_context,
  11251.                         (krb5_pointer)&ttyfd,
  11252.                         &outbuf
  11253.                         )
  11254.         )
  11255.                 goto bad2;
  11256. #else /* COMMENT */
  11257.             msglen = htonl(outbuf.length);
  11258.             if (ttol((CHAR *)&msglen,4) != 4) {
  11259.                 status = -1;
  11260.                 goto bad2;
  11261.             }
  11262.             if ( outbuf.length ) {
  11263.                 if (ttol(outbuf.data,outbuf.length) != outbuf.length) {
  11264.                     status = -1;
  11265.                     goto bad2;
  11266.                 }
  11267.             }
  11268. #endif /* COMMENT */
  11269.         }
  11270.         else { /* Dummy write to signal no forwarding */
  11271. #ifndef COMMENT
  11272.             outbuf.length = 0;
  11273.             if (status = krb5_write_message(k5_context,
  11274.                         (krb5_pointer)&ttyfd,
  11275.                         &outbuf
  11276.                         )
  11277.         )
  11278.                 goto bad2;
  11279. #else /* COMMENT */
  11280.             msglen = htonl(0);
  11281.             if (ttol((CHAR *)&msglen,4) != 4) {
  11282.                 status = -1;
  11283.                 goto bad2;
  11284.             }
  11285. #endif /* COMMENT */
  11286.         }
  11287.  
  11288.         if ((c = ttinc(0)) < 0) {
  11289.             if (c==-1) {
  11290.                 perror(hostname);
  11291.             } else {
  11292.                 printf("ck_krb_rlogin: bad connection with remote host\r\n");
  11293.             }
  11294.             status = -1;
  11295.             goto bad2;
  11296.         }
  11297.         if (c != 0) {
  11298.             while ((c = ttinc(1)) >= 0) {
  11299.                 (void) printf("%c",c);
  11300.                 if (c == '\n')
  11301.                     break;
  11302.             }
  11303.             status = -1;
  11304.             goto bad2;
  11305.         }
  11306.  
  11307. #ifdef MIT_CURRENT
  11308.         /* This code comes from the new MIT krb-current sources which is not */
  11309.         /* supported in the krb-1.0.5 distribution upon which all of the     */
  11310.         /* shipping libraries are based.                                     */
  11311.  
  11312.         if ( status == 0 ) {        /* success */
  11313.             krb5_boolean similar;
  11314.         krb5_keyblock * key = 0;
  11315.  
  11316.             if (status = krb5_c_enctype_compare( k5_context,
  11317.                                                  ENCTYPE_DES_CBC_CRC,
  11318. #ifdef HEIMDAL
  11319.                                                  ret_cred->session.keytype,
  11320. #else /* HEIMDAL */
  11321.                                                  ret_cred->keyblock.enctype,
  11322. #endif /* HEIMDAL */
  11323.                                                  &similar)) {
  11324.                 krb5_free_creds(k5_context, ret_cred);
  11325.                 ret_cred = NULL;
  11326.                 return(-1);
  11327.             }
  11328.  
  11329.             /* what is do_inband for? */
  11330.         if ( similar ) {
  11331.         do_inband = 0;
  11332.             } else {
  11333.                 do_inband = 1;
  11334.  
  11335.         status = krb5_auth_con_getlocalsubkey( k5_context,
  11336.                                auth_context,
  11337.                                &key);
  11338.         if ((status || !key) && encrypt_flag )
  11339.             goto bad2;
  11340.             }
  11341.         if ( key == 0 ) {
  11342. #ifdef HEIMDAL
  11343.         key = &ret_cred->session;
  11344. #else /* HEIMDAL */
  11345.         key = &ret_cred->keyblock;
  11346. #endif /* HEIMDAL */
  11347.             }
  11348.  
  11349.         rcmd_stream_init_krb5(key, encrypt_flag, 1);
  11350.         if ( encrypt_flag )
  11351.         rlog_encrypt = 1;
  11352.         }
  11353. #else /* MIT_CURRENT */
  11354.         if ( status ) {
  11355.             /* should check for KDC_PR_UNKNOWN, NO_TKT_FILE here -- XXX */
  11356.             if (status != -1)
  11357.                 printf("[e]klogin to host %s failed - %s\r\n",hostname,
  11358.                          error_message(status));
  11359.             goto bad2;
  11360.         }
  11361.  
  11362.         if ( encrypt_flag ) {
  11363.             /* if we are encrypting we need to setup the encryption */
  11364.             /* routines.  setup eblock for des_read and write       */
  11365. #ifdef HEIMDAL
  11366.             krb5_use_enctype(k5_context, &eblock,
  11367.                               ret_cred->session.keytype
  11368.                               );
  11369. #else /* HEIMDAL */
  11370.             krb5_use_enctype(k5_context, &eblock,
  11371.                               ret_cred->keyblock.enctype
  11372.                               );
  11373. #endif /* HEIMDAL */
  11374. #ifdef HEIMDAL
  11375.             status = krb5_process_key(k5_context,
  11376.                                        &eblock,
  11377.                                        &ret_cred->session
  11378.                                        );
  11379. #else /* HEIMDAL */
  11380.             status = krb5_process_key(k5_context,
  11381.                                        &eblock,
  11382.                                        &ret_cred->keyblock
  11383.                                        );
  11384. #endif /* HEIMDAL */
  11385.             if (status) {
  11386.                 printf("Cannot process session key : %s.\r\n",
  11387.                          error_message(status)
  11388.                          );
  11389.                 goto bad2;
  11390.             }
  11391.             rlog_encrypt = 1;
  11392.         }
  11393.  
  11394. #endif /* MIT_CURRENT */
  11395.         return (0);     /* success */
  11396.  
  11397.       bad2:
  11398.       bad:
  11399.  
  11400.         if (ret_cred) {
  11401.             krb5_free_creds(k5_context, ret_cred);
  11402.             ret_cred = NULL;
  11403.         }
  11404.         return (status);
  11405. #else /* KRB5 */
  11406.         return(-1);
  11407. #endif /* KRB5 */
  11408.     } else if (kversion == 4) {
  11409. #ifdef KRB4
  11410.         debug(F100,"ck_krb_rlogin version 4","",0);
  11411.  
  11412.         realm = (char *)krb_realmofhost(szHostName);
  11413.         if ((realm == NULL) || (realm[0] == '\0')) {
  11414.             realm = krb4_d_realm;
  11415.         }
  11416.  
  11417.         ttoc(0);        /* write a NUL */
  11418.  
  11419.         status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
  11420.                                ttyfd,
  11421.                                &k4_auth,
  11422.                                krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  11423.                                hostname,
  11424.                                realm,
  11425.                                (unsigned long) getpid(),
  11426.                                &k4_msg_data,
  11427.                                (CREDENTIALS *)&cred,
  11428. #ifdef CK_ENCRYPTION
  11429.                                &k4_sched,
  11430. #else /* ENCRYPTION */
  11431.                                NULL,
  11432. #endif /* ENCRYPTION */
  11433.                                l_addr,
  11434.                                r_addr,
  11435.                                "KCMDV0.1");
  11436.         debug(F111,"ck_krb_rlogin","krb_sendauth",status);
  11437.         if (status != KSUCCESS) {
  11438.             printf( "krb_sendauth failed: %s\r\n",
  11439.             krb_get_err_text_entry(status)
  11440.             );
  11441.             return(-1);
  11442.         }
  11443.         ttol(remoteuser,strlen(remoteuser)+1);
  11444.         ttol(term_speed,strlen(term_speed)+1);
  11445.  
  11446.       reread:
  11447.         if ((c = ttinc(0)) < 0) {
  11448.             printf("rcmd: bad connection with remote host\r\n");
  11449.             return(-1);
  11450.         }
  11451.         debug(F111,"ck_krb_rlogin","first byte",c);
  11452.  
  11453.         if (c != 0) {
  11454.             char *check = "ld.so: warning:";
  11455.             /* If rlogind was compiled on SunOS4, and it somehow
  11456.             got the shared library version numbers wrong, it
  11457.             may give an ld.so warning about an old version of a
  11458.             shared library.  Just ignore any such warning.
  11459.             Note that the warning is a characteristic of the
  11460.             server; we may not ourselves be running under
  11461.             SunOS4.  */
  11462.             if (c == 'l') {
  11463.                 char *p;
  11464.                 char cc;
  11465.  
  11466.                 p = &check[1];
  11467.                 while ((c = ttinc(0)) >= 0) {
  11468.                     if (*p == '\0') {
  11469.                         if (c == '\n')
  11470.                             break;
  11471.                     } else {
  11472.                         if (c != *p)
  11473.                             break;
  11474.                         ++p;
  11475.                     }
  11476.                 }
  11477.  
  11478.                 if (*p == '\0')
  11479.                     goto reread;
  11480.             }
  11481.  
  11482.             printf(check);
  11483.             while ((c = ttinc(1)) >= 0) {
  11484.                 printf("%c",c);
  11485.                 if (c == '\n')
  11486.                     break;
  11487.             }
  11488.             debug(F110,"ck_krb_rlogin","fatal error 1",0);
  11489.             return(-1);
  11490.         }
  11491.  
  11492. #ifdef CK_ENCRYPTION
  11493.         if ( encrypt_flag ) {
  11494.             /* if we are encrypting we need to setup the encryption */
  11495.             /* routines.                                            */
  11496.             des_key_sched(cred.session, k4_sched);
  11497.             rlog_encrypt = 1;
  11498.         }
  11499. #endif /* ENCRYPTION */
  11500. #else /* KRB4 */
  11501.         return(-1);
  11502. #endif /* KRB4 */
  11503.     }
  11504.     return(0); /* success */
  11505. }
  11506.  
  11507. #define SRAND    srand
  11508. #define RAND    rand
  11509. #define RAND_TYPE    int
  11510.  
  11511. static long
  11512. random_confounder(size, fillin)
  11513. size_t size;
  11514. char * fillin;
  11515. {
  11516.     static int seeded = 0;
  11517.     register unsigned char *real_fill;
  11518.     RAND_TYPE    rval;
  11519.  
  11520.     if (!seeded) {
  11521.     /* time() defined in 4.12.2.4, but returns a time_t, which is an
  11522.        "arithmetic type" (4.12.1) */
  11523.     rval = (RAND_TYPE) time(0);
  11524.     SRAND(rval);
  11525.     rval = RAND();
  11526.     rval ^= getpid();
  11527.     SRAND(rval);
  11528.     seeded = 1;
  11529.     }
  11530.  
  11531.     real_fill = (unsigned char *)fillin;
  11532.     while (size > 0) {
  11533.     rval = RAND();
  11534.     *real_fill = rval & 0xff;
  11535.     real_fill++;
  11536.     size--;
  11537.     if (size) {
  11538.         *real_fill = (rval >> 8) & 0xff;
  11539.         real_fill++;
  11540.         size--;
  11541.     }
  11542.     }
  11543.     return 0;
  11544. }
  11545.  
  11546. #ifdef KRB5
  11547. int
  11548. krb5_des_avail(fd)
  11549.     int fd;
  11550. {
  11551.     return(nstored);
  11552. }
  11553.  
  11554. int
  11555. krb5_des_read(fd, buf, len)
  11556.      int fd;
  11557.      register char *buf;
  11558.      int len;
  11559. {
  11560.     int nreturned = 0;
  11561.     long net_len,rd_len;
  11562.     int cc;
  11563.     unsigned char len_buf[4];
  11564.     krb5_error_code status;
  11565.     unsigned char c;
  11566.     int gotzero = 0;
  11567. #ifdef MIT_CURRENT
  11568.     krb5_data plain;
  11569.     krb5_enc_data cipher;
  11570. #endif /* MIT_CURRENT */
  11571.  
  11572.     debug(F111,"krb5_des_read","len",len);
  11573.     debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
  11574.     if ( !rlog_encrypt ) {
  11575.         cc = net_read(fd, buf, len);
  11576.         debug(F111,"krb5_des_read","chars read",cc);
  11577.         if ( cc < 0 )
  11578.             netclos();
  11579.         return(cc);
  11580.     }
  11581.  
  11582.     if (nstored >= len) {
  11583.         if ( buf ) {
  11584.             memcpy(buf, store_ptr, len);        /* safe */
  11585.             store_ptr += len;
  11586.             nstored -= len;
  11587.             return(len);
  11588.         } else
  11589.             return(0);
  11590.     } else if (nstored) {
  11591.         if ( buf ) {
  11592.             memcpy(buf, store_ptr, nstored);    /* safe */
  11593.             nreturned += nstored;
  11594.             buf += nstored;
  11595.             len -= nstored;
  11596.             nstored = 0;
  11597.         }
  11598.         else
  11599.             return(0);
  11600.     }
  11601.  
  11602.     /* See the comment in v4_des_read. */
  11603.     do {
  11604.         cc = net_read(fd, &c, 1);
  11605.         /* we should check for non-blocking here, but we'd have
  11606.         to make it save partial reads as well. */
  11607.         if (cc <= 0) {
  11608.             return cc; /* read error */
  11609.         }
  11610.         if (cc == 1) {
  11611.             if (c == 0) gotzero = 1;
  11612.         }
  11613.     } while (!gotzero);
  11614.  
  11615.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11616.     rd_len = c;
  11617.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11618.     rd_len = (rd_len << 8) | c;
  11619.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11620.     rd_len = (rd_len << 8) | c;
  11621.  
  11622. #ifdef MIT_CURRENT
  11623.     if (ret = krb5_c_encrypt_length(k5_context, k5_session_key->enctype,
  11624.                               rd_len, &net_len)) {
  11625.     errno = ret;
  11626.     return(-1);
  11627.     }
  11628. #else /* MIT_CURRENT */
  11629.     net_len = krb5_encrypt_size(rd_len, eblock.crypto_entry);
  11630. #endif /* MIT_CURRENT */
  11631.     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
  11632.     /* preposterous length; assume out-of-sync; only
  11633.        recourse is to close connection, so return 0 */
  11634.     printf("Read size problem.\r\n");
  11635.     return(0);
  11636.     }
  11637.     if ((cc = net_read(fd, desinbuf.data, net_len)) != net_len )
  11638.     {
  11639.     /* pipe must have closed, return 0 */
  11640.     printf(    "Read error: length received %d != expected %d.\r\n",
  11641.         cc,
  11642.         net_len
  11643.         );
  11644.         return(cc);
  11645.     }
  11646.     /* decrypt info */
  11647. #ifdef MIT_CURRENT
  11648.     cipher.enctype = ENCTYPE_UNKNOWN;
  11649.     cipher.ciphertext.length = net_len;
  11650.     cipher.ciphertext.data = desinbuf.data;
  11651.     plain.length = sizeof(storage);
  11652.     plain.data = storage;
  11653.  
  11654.     if ( status = krb5_c_decrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
  11655.              encivec_i.length?&encivec_i:0,
  11656.              &cipher,&plain) ) {
  11657.     /* probably out of sync */
  11658.     printf("Cannot decrypt data from network: %s\r\n",
  11659.                  error_message(status));
  11660.     errno = EIO;
  11661.     return(-1);
  11662.     }
  11663. #else /* MIT_CURRENT */
  11664.     if ((status = krb5_decrypt(k5_context, desinbuf.data,
  11665.               (krb5_pointer) storage,
  11666.               net_len,
  11667.               &eblock, 0))) {
  11668.     printf("Cannot decrypt data from network: %s\r\n",
  11669.                  error_message(status));
  11670.     return(0);
  11671.     }
  11672. #endif /* MIT_CURRENT */
  11673.     store_ptr = storage;
  11674.     nstored = rd_len;
  11675.     if ( !buf ) {
  11676.         return(0);
  11677.     }
  11678.  
  11679.     if (nstored > len) {
  11680.     memcpy(buf, store_ptr, len);            /* safe */
  11681.     nreturned += len;
  11682.     store_ptr += len;
  11683.     nstored -= len;
  11684.     } else {
  11685.     memcpy(buf, store_ptr, nstored);        /* safe */
  11686.     nreturned += nstored;
  11687.     nstored = 0;
  11688.     }
  11689.     return(nreturned);
  11690. }
  11691.  
  11692. int
  11693. krb5_des_write(fd, buf, len)
  11694.      int fd;
  11695.      char *buf;
  11696.      int len;
  11697. {
  11698.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  11699.     int cc;
  11700.     krb5_error_code status;
  11701. #ifdef MIT_CURRENT
  11702.     krb5_data plain;
  11703.     krb5_enc_data cipher;
  11704. #endif /* MIT_CURRENT */
  11705.  
  11706.     debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
  11707.     if ( !rlog_encrypt ) {
  11708.         cc = net_write(fd, buf, len);
  11709.         debug(F111,"net_write","chars written",cc);
  11710.         return(cc != len ? -1 : len);
  11711.     }
  11712.  
  11713. #ifdef MIT_CURRENT
  11714.     plain.data = buf;
  11715.     plain.length = len;
  11716.  
  11717.     cipher.ciphertext.length = sizeof(des_outpkt)-4;
  11718.     cipher.ciphertext.data = desoutbuf.data;
  11719.  
  11720.     if ( status = krb5_c_encrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
  11721.              encivec_o.length?&encivec_o:0,
  11722.              &plain, &cipher)) {
  11723.           printf("Write encrypt problem: %s.\r\n",
  11724.                  error_message(status));
  11725.     errno = EIO;
  11726.     return(-1);
  11727.     }
  11728.     desoutbuf.length = cipher.ciphertext.length;
  11729. #else /* MIT_CURRENT */
  11730.     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
  11731.     if (desoutbuf.length > sizeof(des_outpkt)-4){
  11732.           printf("Write size problem.\r\n");
  11733.     return(-1);
  11734.     }
  11735.     if ((status = krb5_encrypt(k5_context, (krb5_pointer)buf,
  11736.               desoutbuf.data,
  11737.               len,
  11738.               &eblock,
  11739.               0))){
  11740.           printf("Write encrypt problem: %s.\r\n",
  11741.                  error_message(status));
  11742.     return(-1);
  11743.     }
  11744. #endif /* MIT_CURRENT */
  11745.  
  11746.     len_buf[0] = (len & 0xff000000) >> 24;
  11747.     len_buf[1] = (len & 0xff0000) >> 16;
  11748.     len_buf[2] = (len & 0xff00) >> 8;
  11749.     len_buf[3] = (len & 0xff);
  11750.  
  11751.     if (net_write(fd, des_outpkt,desoutbuf.length+4)
  11752.          != desoutbuf.length+4){
  11753.         printf("Could not write out all data\r\n");
  11754.     return(-1);
  11755.     }
  11756.     else return(len);
  11757. }
  11758. #endif /* KRB5 */
  11759.  
  11760. #ifdef KRB4
  11761. /*
  11762.  * Note that the encrypted rlogin packets take the form of a four-byte
  11763.  * length followed by encrypted data.  On writing the data out, a significant
  11764.  * performance penalty is suffered (at least one RTT per character, two if we
  11765.  * are waiting for a shell to echo) by writing the data separately from the
  11766.  * length.  So, unlike the input buffer, which just contains the output
  11767.  * data, the output buffer represents the entire packet.
  11768.  */
  11769.  
  11770. int
  11771. krb4_des_avail(fd)
  11772.     int fd;
  11773. {
  11774.     return(nstored);
  11775. }
  11776.  
  11777. int
  11778. krb4_des_read(fd, buf, len)
  11779. int fd;
  11780. register char *buf;
  11781. int len;
  11782. {
  11783.     int nreturned = 0;
  11784.     unsigned long net_len, rd_len;
  11785.     int cc;
  11786.     unsigned char c;
  11787.     int gotzero = 0;
  11788.  
  11789.     debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
  11790.     debug(F111,"krb4_des_read","len",len);
  11791.     if ( !rlog_encrypt ) {
  11792.         cc = net_read(fd, buf, len);
  11793.         debug(F111,"krb4_des_read","chars read",cc);
  11794.         if ( cc < 0 )
  11795.             netclos();
  11796.         return(cc);
  11797.     }
  11798.  
  11799.     if (nstored >= len) {
  11800.         if ( buf ) {
  11801.             debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
  11802.             memcpy(buf, store_ptr, len);        /* safe */
  11803.             store_ptr += len;
  11804.             nstored -= len;
  11805.             return(len);
  11806.         } else
  11807.             return(0);
  11808.     } else if (nstored) {
  11809.         if ( buf ) {
  11810.             debug(F111,"krb4_des_read (nstored)","nstored",nstored);
  11811.             memcpy(buf, store_ptr, nstored);    /* safe */
  11812.             nreturned += nstored;
  11813.             buf += nstored;
  11814.             len -= nstored;
  11815.             nstored = 0;
  11816.         } else
  11817.             return(0);
  11818.     }
  11819.  
  11820.     /* We're fetching the length which is MSB first, and the MSB
  11821.     has to be zero unless the client is sending more than 2^24
  11822.     (16M) bytes in a single write (which is why this code is in
  11823.     rlogin but not rcp or rsh.) The only reasons we'd get something
  11824.     other than zero are:
  11825.     -- corruption of the tcp stream (which will show up when
  11826.     everything else is out of sync too)
  11827.     -- un-caught Berkeley-style "pseudo out-of-band data" which
  11828.     happens any time the user hits ^C twice.
  11829.     The latter is *very* common, as shown by an 'rlogin -x -d'
  11830.     using the CNS V4 rlogin.         Mark EIchin 1/95
  11831.     */
  11832.     debug(F110,"krb4_des_read",
  11833.       "about to call net_read() this will block",
  11834.       0
  11835.       );
  11836.     do {
  11837.         cc = net_read(fd, &c, 1);
  11838.         debug(F111,"net_read","chars read",cc);
  11839.         if (cc <= 0) {
  11840.             netclos();
  11841.             return(-1);
  11842.         }
  11843.         if (cc != 1) return 0; /* read error */
  11844.         if (cc == 1) {
  11845.             if (c == 0) gotzero = 1;
  11846.         }
  11847.     } while (!gotzero);
  11848.  
  11849.     debug(F110,"krb4_des_read","gotzero",0);
  11850.     cc = net_read(fd, &c, 1);
  11851.     debug(F111,"net_read","chars read",cc);
  11852.     if (cc < 0) {
  11853.         netclos();
  11854.         return(-1);
  11855.     } else if ( cc != 1 )
  11856.         return(0);
  11857.     net_len = c;
  11858.     cc = net_read(fd, &c, 1);
  11859.     debug(F111,"net_read","chars read",cc);
  11860.     if (cc < 0) {
  11861.         netclos();
  11862.         return(-1);
  11863.     } else if ( cc != 1 )
  11864.         return(0);
  11865.     net_len = (net_len << 8) | c;
  11866.     debug(F111,"net_read","chars read",cc);
  11867.     cc = net_read(fd, &c, 1);
  11868.     if (cc < 0) {
  11869.         netclos();
  11870.         return(-1);
  11871.     } else if ( cc != 1 )
  11872.         return(0);
  11873.     net_len = (net_len << 8) | c;
  11874.     debug(F111,"krb4_des_read","net_len",net_len);
  11875.  
  11876.     /* Note: net_len is unsigned */
  11877.     if (net_len > sizeof(des_inbuf)) {
  11878.         /* XXX preposterous length, probably out of sync.
  11879.         act as if pipe closed */
  11880.         return(0);
  11881.     }
  11882.     /* the writer tells us how much real data we are getting, but
  11883.     we need to read the pad bytes (8-byte boundary) */
  11884. #ifndef roundup
  11885. #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
  11886. #endif /* roundup */
  11887.     rd_len = roundup(net_len, 8);
  11888.     debug(F111,"krb4_des_read","rd_len",rd_len);
  11889.     cc = net_read(fd, des_inbuf, rd_len);
  11890.     debug(F111,"net_read","chars read",cc);
  11891.     if (cc < 0) {
  11892.         netclos();
  11893.         return(-1);
  11894.     } else if ( cc != rd_len )
  11895.         return(0);
  11896.  
  11897.     hexdump("krb4_des_read des_inbuf",des_inbuf,8);
  11898. #ifdef CK_ENCRYPTION
  11899. #ifdef KRB524
  11900.     (void) des_pcbc_encrypt(des_inbuf,
  11901.                              storage,
  11902.                              (net_len < 8) ? 8 : net_len,
  11903.                              k4_sched,
  11904.                              cred.session,
  11905.                              DECRYPT);
  11906. #else /* KRB524 */
  11907.     (void) des_pcbc_encrypt((Block *)des_inbuf,
  11908.                              (Block *)storage,
  11909.                              (net_len < 8) ? 8 : net_len,
  11910.                              k4_sched,
  11911.                              &cred.session,
  11912.                              DECRYPT);
  11913. #endif /* KRB524 */
  11914. #endif /* ENCRYPTION */
  11915.     hexdump("krb4_des_read storage",storage,8);
  11916.  
  11917.     /*
  11918.     * when the cleartext block is < 8 bytes, it is "right-justified"
  11919.     * in the block, so we need to adjust the pointer to the data
  11920.     */
  11921.     if (net_len < 8)
  11922.         store_ptr = storage + 8 - net_len;
  11923.     else
  11924.         store_ptr = storage;
  11925.     nstored = net_len;
  11926.  
  11927.     if ( !buf )
  11928.         return(0);
  11929.  
  11930.     if (nstored > len) {
  11931.         memcpy(buf, store_ptr, len);            /* safe */
  11932.         nreturned += len;
  11933.         store_ptr += len;
  11934.         nstored -= len;
  11935.     } else {
  11936.         memcpy(buf, store_ptr, nstored);        /* safe */
  11937.         nreturned += nstored;
  11938.         nstored = 0;
  11939.     }
  11940.  
  11941.     debug(F111,"net_read","nreturned",nreturned);
  11942.     return(nreturned);
  11943. }
  11944.  
  11945. int
  11946. krb4_des_write(fd, buf, len)
  11947. int fd;
  11948. char *buf;
  11949. int len;
  11950. {
  11951.     static char garbage_buf[8];
  11952.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  11953.     int cc;
  11954.  
  11955.     debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
  11956.     if ( !rlog_encrypt ) {
  11957.         cc = net_write(fd, buf, len);
  11958.         debug(F111,"net_write","chars written",cc);
  11959.         return(cc);
  11960.     }
  11961.  
  11962.     /*
  11963.     * pcbc_encrypt outputs in 8-byte (64 bit) increments
  11964.     *
  11965.     * it zero-fills the cleartext to 8-byte padding,
  11966.     * so if we have cleartext of < 8 bytes, we want
  11967.     * to insert random garbage before it so that the ciphertext
  11968.     * differs for each transmission of the same cleartext.
  11969.     * if len < 8 - sizeof(long), sizeof(long) bytes of random
  11970.     * garbage should be sufficient; leave the rest as-is in the buffer.
  11971.     * if len > 8 - sizeof(long), just garbage fill the rest.
  11972.     */
  11973.     if (len < 8) {
  11974.         random_confounder(8 - len, garbage_buf);
  11975.         /* this "right-justifies" the data in the buffer */
  11976.         (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
  11977.         hexdump("krb4_des_write garbage_buf",garbage_buf,8);
  11978.     } else
  11979.         hexdump("krb4_des_write buf",buf,8);
  11980. #ifdef CK_ENCRYPTION
  11981. #ifdef KRB524
  11982.     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
  11983.                              des_outpkt+4,
  11984.                              (len < 8) ? 8 : len,
  11985.                              k4_sched,
  11986.                              cred.session,
  11987.                              ENCRYPT);
  11988. #else /* KRB524 */
  11989.     (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
  11990.                              (Block *)(des_outpkt+4),
  11991.                              (len < 8) ? 8 : len,
  11992.                              k4_sched,
  11993.                              &cred.session,
  11994.                              ENCRYPT);
  11995. #endif /* KRB524 */
  11996. #endif /* ENCRYPTION */
  11997.     if ( len < 8 )
  11998.         hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
  11999.     else
  12000.         hexdump("krb4_des_write (post pcbc) buf",buf,8);
  12001.     hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
  12002.  
  12003.     /* tell the other end the real amount, but send an 8-byte padded
  12004.     packet */
  12005.     len_buf[0] = (len & 0xff000000) >> 24;
  12006.     len_buf[1] = (len & 0xff0000) >> 16;
  12007.     len_buf[2] = (len & 0xff00) >> 8;
  12008.     len_buf[3] = (len & 0xff);
  12009.     hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
  12010.     cc = net_write(fd, des_outpkt, roundup(len,8)+4);
  12011.     debug(F111,"net_write","chars written",cc);
  12012.     return(len);
  12013. }
  12014. #endif /* KRB4 */
  12015. #endif /* RLOGCODE */
  12016.  
  12017. #ifdef KRB524
  12018. #ifndef OS2
  12019. /* The following functions are missing from the compatibility library */
  12020. const char *
  12021. krb_get_err_text_entry(r) int r;
  12022. {
  12023.     extern char krb_err_text[];
  12024.     return(krb_err_txt[r]);
  12025. }
  12026. #endif /* OS2 */
  12027. #endif /* KRB524 */
  12028. #endif /* CK_KERBEROS */
  12029.  
  12030. #ifdef CK_KERBEROS
  12031. #ifdef KRB5_U2U
  12032. /* Kerberos 5 User to User Client */
  12033. int
  12034. k5_user_to_user_client_auth()
  12035. {
  12036.     extern int ttyfd;
  12037.     register int retval, i;
  12038.     char **srealms;            /* realm(s) of server */
  12039.     char *princ;        /* principal in credentials cache */
  12040.     krb5_ccache cc;
  12041.     krb5_creds creds, *new_creds;
  12042.     krb5_data reply, msg, msgtext, princ_data;
  12043.     krb5_ticket * ticket = NULL;
  12044.  
  12045.     if (retval = k5_get_ccache(k5_context,&cc,NULL))
  12046.     {
  12047.         com_err("uu-client", retval, "getting credentials cache");
  12048.         return(-1);
  12049.     }
  12050.  
  12051.     memset ((char*)&creds, 0, sizeof(creds));
  12052.     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
  12053.     {
  12054.         com_err("uu-client", retval, "getting principal name");
  12055.         return(-1);
  12056.     }
  12057.  
  12058.     if (retval = krb5_get_host_realm(k5_context, szHostName, &srealms))
  12059.     {
  12060.         com_err("uu-client", retval, "getting realms for \"%s\"", szHostName);
  12061.         return(-1);
  12062.     }
  12063.  
  12064.     if (retval = krb5_build_principal_ext(k5_context, &creds.server,
  12065.                       krb5_princ_realm(k5_context,
  12066.                              creds.client)->length,
  12067.                       krb5_princ_realm(k5_context,
  12068.                              creds.client)->data,
  12069.                       6, "krbtgt",
  12070.                       krb5_princ_realm(k5_context,
  12071.                              creds.client)->length,
  12072.                       krb5_princ_realm(k5_context,
  12073.                              creds.client)->data,
  12074.                       0))
  12075.     {
  12076.         com_err("uu-client", retval, "setting up tgt server name");
  12077.         return(-1);
  12078.     }
  12079.  
  12080.     /* Get TGT from credentials cache */
  12081.     if (retval = krb5_get_credentials(k5_context, KRB5_GC_CACHED, cc,
  12082.                                        &creds, &new_creds))
  12083.     {
  12084.         com_err("uu-client", retval, "getting TGT");
  12085.         return(-1);
  12086.     }
  12087.  
  12088.     if (retval = krb5_unparse_name(k5_context, creds.client, &princ)) {
  12089.         com_err("uu-client", retval, "printing principal name");
  12090.         return(-1);
  12091.     }
  12092.     i = strlen(princ) + 1;
  12093.     princ_data.data = princ;
  12094.     princ_data.length = i;        /* include null terminator for
  12095.                        server's convenience */
  12096.     retval = krb5_write_message(k5_context,
  12097.                 (krb5_pointer) &ttyfd, &princ_data);
  12098.     if (retval)
  12099.     {
  12100.         com_err("uu-client", retval, "sending principal name to server");
  12101.         return(-1);
  12102.     }
  12103.     krb5_free_unparsed_name(k5_context,princ);
  12104.  
  12105.     retval = krb5_write_message(k5_context,
  12106.                 (krb5_pointer) &ttyfd, &new_creds->ticket);
  12107.     if (retval)
  12108.     {
  12109.         com_err("uu-client", retval, "sending ticket to server");
  12110.         return(-1);
  12111.     }
  12112.  
  12113.     retval = krb5_read_message(k5_context, (krb5_pointer) &ttyfd, &reply);
  12114.     if (retval)
  12115.     {
  12116.     com_err("uu-client", retval, "reading reply from server");
  12117.         return(-1);
  12118.     }
  12119.  
  12120.     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
  12121.           com_err("uu-client", retval, "initializing the auth_context");
  12122.         return(-1);
  12123.     }
  12124.  
  12125.     if (!krb5_d_no_addresses) {
  12126.       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  12127.             KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
  12128.             KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
  12129.           com_err("uu-client", retval, "generating addrs for auth_context");
  12130.         return(-1);
  12131.       }
  12132.     }
  12133.  
  12134.     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
  12135.                     KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
  12136.     com_err("uu-client", retval, "initializing the auth_context flags");
  12137.         return(-1);
  12138.     }
  12139.  
  12140.     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
  12141.                           &new_creds->keyblock)) {
  12142.     com_err("uu-client", retval, "setting useruserkey for authcontext");
  12143.     return(-1);
  12144.     }
  12145.  
  12146.     /* read the ap_req to get the session key */
  12147.     retval = krb5_rd_req(k5_context, &auth_context, &reply,
  12148.                           NULL, NULL, NULL, &ticket);
  12149.     if (retval) {
  12150.         com_err("uu-client", retval, "reading AP_REQ from server");
  12151.         return(-1);
  12152.     }
  12153.  
  12154.     if (k5_u2u_read_msg(k5_context,&msg) < 0)
  12155.         return(-1);
  12156.  
  12157.     if ( strcmp("Kermit implements Kerberos 5 User to User",msg.data) )
  12158.         return(-1);
  12159.     krb5_free_data_contents(k5_context,&msg);
  12160.  
  12161.     msgtext.data = "As do I! :-)";
  12162.     msgtext.length = strlen(msgtext.data)+1;
  12163.  
  12164.     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
  12165.         return(-1);
  12166.  
  12167.     if (retval = krb5_unparse_name(k5_context,
  12168. #ifdef HEIMDAL
  12169.                                     ticket->client,
  12170. #else /* HEIMDAL */
  12171.                                     ticket->enc_part2->client,
  12172. #endif /* HEIMDAL */
  12173.                                     &princ))
  12174.         com_err("uu-client", retval, "while unparsing client name");
  12175.     else {
  12176.         ckstrncpy(szUserNameAuthenticated,princ,UIDBUFLEN);
  12177.         validUser = AUTH_VALID;
  12178.         authentication_version = AUTHTYPE_KERBEROS_V5;
  12179.         if ( !quiet )
  12180.             printf("Peer name is \"%s\"\n", princ);
  12181.         krb5_free_unparsed_name(k5_context,princ);
  12182.     }
  12183.     return 0;
  12184. }
  12185.  
  12186. /* Kerberos 5 User to User Server */
  12187.  
  12188. int
  12189. k5_user_to_user_server_auth()
  12190. {
  12191.     krb5_data pname_data, tkt_data;
  12192.     int retval;
  12193.     krb5_creds creds, *new_creds;
  12194.     krb5_ccache cc;
  12195.     krb5_data msg, msgtext;
  12196.     extern int ttyfd;
  12197.  
  12198.     if (retval = krb5_read_message(k5_context,
  12199.                    (krb5_pointer) &ttyfd, &pname_data)) {
  12200.         com_err ("uu-server", retval, "reading pname");
  12201.         return(-1);
  12202.     }
  12203.     /* client sends it already null-terminated. */
  12204.     if ( !quiet )
  12205.         printf ("Peer name is \"%s\".\n", pname_data.data);
  12206.     ckstrncpy(szUserNameAuthenticated,pname_data.data,UIDBUFLEN);
  12207.     validUser = AUTH_VALID;
  12208.     authentication_version = AUTHTYPE_KERBEROS_V5;
  12209.  
  12210.     if (retval = krb5_read_message(k5_context,
  12211.                    (krb5_pointer) &ttyfd, &tkt_data)) {
  12212.         com_err ("uu-server", retval, "reading ticket data");
  12213.         return(-1);
  12214.     }
  12215.  
  12216.     if (retval = k5_get_ccache(k5_context,&cc,NULL))
  12217.     {
  12218.         com_err("uu-server", retval, "getting credentials cache");
  12219.         return(-1);
  12220.     }
  12221.  
  12222.     memset ((char*)&creds, 0, sizeof(creds));
  12223.     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
  12224.     {
  12225.         com_err("uu-server", retval, "getting principal name");
  12226.         return(-1);
  12227.     }
  12228.  
  12229.     if (retval = krb5_parse_name(k5_context, pname_data.data, &creds.server))
  12230.     {
  12231.         com_err("uu-server", retval, "parsing client name");
  12232.         return(-1);
  12233.     }
  12234.     creds.second_ticket = tkt_data;
  12235.  
  12236.     if (retval = krb5_get_credentials(k5_context, KRB5_GC_USER_USER,
  12237.                                        cc, &creds, &new_creds))
  12238.     {
  12239.         com_err("uu-server", retval, "getting user-user ticket");
  12240.         return(-1);
  12241.     }
  12242.  
  12243.     /* send a ticket/authenticator to the other side, so it can get the key
  12244.        we're using for the krb_safe below. */
  12245.  
  12246.     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
  12247.           com_err("uu-server", retval, "making auth_context");
  12248.         return(-1);
  12249.     }
  12250.  
  12251.     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
  12252.                                          KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
  12253.     com_err("uu-server", retval, "initializing the auth_context flags");
  12254.         return(-1);
  12255.     }
  12256.  
  12257.     if (!krb5_d_no_addresses) {
  12258.       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  12259.                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
  12260.                 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
  12261.         com_err("uu-server", retval, "generating addrs for auth_context");
  12262.         return(-1);
  12263.       }
  12264.     }
  12265.  
  12266.     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
  12267.                           &new_creds->keyblock)) {
  12268.     com_err("uu-server", retval, "setting useruserkey for authcontext");
  12269.     return(-1);
  12270.     }
  12271.  
  12272.     if (retval = krb5_mk_req_extended(k5_context, &auth_context,
  12273.                       AP_OPTS_USE_SESSION_KEY |
  12274.                                       AP_OPTS_MUTUAL_REQUIRED,
  12275.                       NULL, new_creds, &msg)) {
  12276.           com_err("uu-server", retval, "making AP_REQ");
  12277.         return(-1);
  12278.     }
  12279.     retval = krb5_write_message(k5_context, (krb5_pointer) &ttyfd, &msg);
  12280.     if (retval) {
  12281.         com_err("uu-server", retval, "writing message to client");
  12282.         return(-1);
  12283.     }
  12284.     krb5_free_data_contents(k5_context,&msg);
  12285.  
  12286.     msgtext.data = "Kermit implements Kerberos 5 User to User";
  12287.     msgtext.length = strlen(msgtext.data)+1;
  12288.  
  12289.     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
  12290.         return(-1);
  12291.  
  12292.     if (k5_u2u_read_msg(k5_context,&msg) < 0)
  12293.         return(-1);
  12294.  
  12295.     if ( strcmp("As do I! :-)",msg.data) )
  12296.         return(-1);
  12297.     krb5_free_data_contents(k5_context,&msg);
  12298.  
  12299.  
  12300.     return(0);
  12301. }
  12302.  
  12303. int
  12304. k5_u2u_read_msg(krb5_context context, int fd, krb5_data * msg)
  12305. {
  12306.     int retval;
  12307.     krb5_data reply;
  12308.  
  12309.     retval = krb5_read_message(context, (krb5_pointer) &fd, &reply);
  12310.     if (retval)
  12311.     {
  12312.         com_err("uu-client", retval, "reading reply");
  12313.         return(-1);
  12314.     }
  12315.  
  12316.     if (retval = krb5_rd_priv(context, auth_context, &reply, msg, NULL)) {
  12317.         com_err("uu-client", retval, "decoding reply");
  12318.         return(-1);
  12319.     }
  12320.     return(0);
  12321. }
  12322.  
  12323. int
  12324. k5_u2u_write_msg(krb5_context context, int fd, krb5_data * msgtext)
  12325. {
  12326.     int retval;
  12327.     krb5_data msg;
  12328.  
  12329.     if (retval = krb5_mk_priv(k5_context, auth_context, msgtext, &msg, NULL))
  12330.     {
  12331.         com_err("uu-server", retval, "encoding message");
  12332.         return(-1);
  12333.     }
  12334.  
  12335.     retval = krb5_write_message(k5_context, (krb5_pointer) &fd, &msg);
  12336.     krb5_free_data_contents(k5_context,&msg);
  12337.     if (retval)
  12338.     {
  12339.     com_err("uu-server", retval, "writing message");
  12340.         return(-1);
  12341.     }
  12342.     return(0);
  12343. }
  12344.  
  12345. int
  12346. krb5_u2u_avail(fd)
  12347.     int fd;
  12348. {
  12349.     return(nstored);
  12350. }
  12351.  
  12352. int
  12353. krb5_u2u_read(fd, buf, len)
  12354.      int fd;
  12355.      register char *buf;
  12356.      int len;
  12357. {
  12358.     int nreturned = 0;
  12359.     krb5_data msg;
  12360.  
  12361.     debug(F111,"krb5_u2u_read","len",len);
  12362.  
  12363.     if ( !buf )
  12364.         return(0);
  12365.  
  12366.     if (nstored >= len) {
  12367.         memcpy(buf, store_ptr, len);        /* safe */
  12368.         store_ptr += len;
  12369.         nstored -= len;
  12370.         return(len);
  12371.     } else if (nstored) {
  12372.         memcpy(buf, store_ptr, nstored);    /* safe */
  12373.         nreturned += nstored;
  12374.         buf += nstored;
  12375.         len -= nstored;
  12376.         nstored = 0;
  12377.     }
  12378.  
  12379.     if (k5_u2u_read_msg(k5_context, fd, &msg) < 0)
  12380.         return(-1);
  12381.  
  12382.     if ( msg.length <= len ) {
  12383.     memcpy(buf, msg.data, msg.length);
  12384.     nreturned += msg.length;
  12385.     nstored = 0;
  12386.     } else {
  12387.     memcpy(buf, msg.data, len);
  12388.     nreturned += len;
  12389.  
  12390.         if ( msg.length - len < sizeof(storage) ) {
  12391.             store_ptr = storage;
  12392.             nstored = msg.length - len;
  12393.             memcpy(storage,msg.data+len,nstored);
  12394.         } else {
  12395.             nstored = 0;
  12396.             return(-1);
  12397.         }
  12398.     }
  12399.     return(nreturned);
  12400. }
  12401.  
  12402. int
  12403. krb5_u2u_write(fd, buf, len)
  12404.      int fd;
  12405.      char *buf;
  12406.      int len;
  12407. {
  12408.     krb5_data msg;
  12409.  
  12410.     msg.length = len;
  12411.     msg.data = buf;
  12412.  
  12413.     if ( k5_u2u_write_msg(k5_context, fd, &msg) < 0 )
  12414.         return(-1);
  12415.     else
  12416.         return(len);
  12417. }
  12418.  
  12419. #endif /* KRB5_U2U */
  12420. #endif /* CK_KERBEROS */
  12421.  
  12422. #ifdef CK_FORWARD_X
  12423. /*
  12424.  
  12425. Copyright (c) 1988  X Consortium
  12426.  
  12427. Permission is hereby granted, free of charge, to any person obtaining a copy
  12428. of this software and associated documentation files (the "Software"), to deal
  12429. in the Software without restriction, including without limitation the rights
  12430. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12431. copies of the Software, and to permit persons to whom the Software is
  12432. furnished to do so, subject to the following conditions:
  12433.  
  12434. The above copyright notice and this permission notice shall be included in
  12435. all copies or substantial portions of the Software.
  12436.  
  12437. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12438. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12439. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  12440. X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  12441. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  12442. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  12443.  
  12444. Except as contained in this notice, the name of the X Consortium shall not be
  12445. used in advertising or otherwise to promote the sale, use or other dealings
  12446. in this Software without prior written authorization from the X Consortium.
  12447.  
  12448. */
  12449. /*  Modified for stand-alone compiling by
  12450.  *  Peter 'Luna' Runestig <peter@runestig.com>
  12451.  */
  12452.  
  12453. #include <stdlib.h>
  12454. #include <string.h>
  12455. #include <fcntl.h>
  12456. #include <sys/stat.h>
  12457. #include <errno.h>
  12458. #include <time.h>
  12459. #define Time_t time_t
  12460.  
  12461. void
  12462. XauDisposeAuth (auth)
  12463. Xauth    *auth;
  12464. {
  12465.     if (auth) {
  12466.     if (auth->address) (void) free (auth->address);
  12467.     if (auth->number) (void) free (auth->number);
  12468.     if (auth->name) (void) free (auth->name);
  12469.     if (auth->data) {
  12470.         (void) bzero (auth->data, auth->data_length);
  12471.         (void) free (auth->data);
  12472.     }
  12473.     free ((char *) auth);
  12474.     }
  12475.     return;
  12476. }
  12477.  
  12478. char *
  12479. XauFileName ()
  12480. {
  12481.     char *slashDotXauthority = "/.Xauthority";
  12482.     char    *name;
  12483.     static char    *buf=NULL;
  12484.     static int    bsize=0;
  12485.     int        size, namelen;
  12486.     extern char * tn_fwdx_xauthority;
  12487.  
  12488.     if ( tn_fwdx_xauthority )
  12489.         return(tn_fwdx_xauthority);
  12490.  
  12491.     if (name = getenv ("XAUTHORITY"))
  12492.     return(name);
  12493.     name = zhome();
  12494.     if ( !name )
  12495.     return(NULL);
  12496.     namelen = strlen (name);
  12497.     size = namelen + strlen(slashDotXauthority) + 1;
  12498.     if (size > bsize) {
  12499.     if (buf)
  12500.         free (buf);
  12501.     buf = malloc ((unsigned) size);
  12502.     if (!buf)
  12503.         return 0;
  12504.     bsize = size;
  12505.     }
  12506.     ckstrncpy (buf, name, bsize);
  12507.     if ( name[namelen-1] != '/'
  12508. #ifdef OS2
  12509.          && name[namelen-1] != '\\'
  12510. #endif /* OS2 */
  12511.          )
  12512.         ckstrncat (buf, slashDotXauthority, bsize);
  12513.     else
  12514.         ckstrncat (buf, &slashDotXauthority[1], bsize);
  12515.     return(buf);
  12516. }
  12517.  
  12518. static int
  12519. binaryEqual (a, b, len)
  12520. register char    *a, *b;
  12521. register int    len;
  12522. {
  12523.     while (len--)
  12524.     if (*a++ != *b++)
  12525.         return 0;
  12526.     return 1;
  12527. }
  12528.  
  12529. #ifndef R_OK
  12530. #define R_OK 04
  12531. #endif /* R_OK */
  12532.  
  12533. Xauth *
  12534. XauGetAuthByAddr (family, address_length, address,
  12535.               number_length, number,
  12536.               name_length, name)
  12537. unsigned int    family;
  12538. unsigned int    address_length;
  12539. const char    *address;
  12540. unsigned int    number_length;
  12541. const char    *number;
  12542. unsigned int    name_length;
  12543. const char    *name;
  12544. {
  12545.     FILE    *auth_file;
  12546.     char    *auth_name;
  12547.     Xauth   *entry;
  12548.  
  12549.     auth_name = XauFileName();
  12550.     if (!auth_name)
  12551.     return 0;
  12552.     if (access (auth_name, R_OK) != 0)        /* checks REAL id */
  12553.     return 0;
  12554.     auth_file = fopen (auth_name, "rb");
  12555.     if (!auth_file)
  12556.     return 0;
  12557.     for (;;) {
  12558.     entry = XauReadAuth (auth_file);
  12559.     if (!entry)
  12560.         break;
  12561.     /*
  12562.      * Match when:
  12563.      *   either family or entry->family are FamilyWild or
  12564.      *    family and entry->family are the same
  12565.      *  and
  12566.      *   either address or entry->address are empty or
  12567.      *    address and entry->address are the same
  12568.      *  and
  12569.      *   either number or entry->number are empty or
  12570.      *    number and entry->number are the same
  12571.      *  and
  12572.      *   either name or entry->name are empty or
  12573.      *    name and entry->name are the same
  12574.      */
  12575.  
  12576. /*    if ((family == FamilyWild || entry->family == FamilyWild ||
  12577.          (entry->family == family &&
  12578.           address_length == entry->address_length &&
  12579.           binaryEqual (entry->address, address, (int)address_length))) &&
  12580.         (number_length == 0 || entry->number_length == 0 ||
  12581.          (number_length == entry->number_length &&
  12582.           binaryEqual (entry->number, number, (int)number_length))) &&
  12583.         (name_length == 0 || entry->name_length == 0 ||
  12584.          (entry->name_length == name_length &&
  12585.            binaryEqual (entry->name, name, (int)name_length)))) */
  12586.     /* the original matching code above doesn't seem to meet the matching
  12587.      * algorithm, it doesn't check if "address_length == 0 ||
  12588.      * entry->address_length == 0". / Luna 2000-02-09
  12589.      */
  12590.     if ((family == FamilyWild || entry->family == FamilyWild ||
  12591.           entry->family == family) &&
  12592.         (address_length == 0 || entry->address_length == 0 ||
  12593.           (address_length == entry->address_length &&
  12594.           binaryEqual (entry->address, address, (int)address_length))) &&
  12595.         (number_length == 0 || entry->number_length == 0 ||
  12596.          (number_length == entry->number_length &&
  12597.           binaryEqual (entry->number, number, (int)number_length))) &&
  12598.         (name_length == 0 || entry->name_length == 0 ||
  12599.          (entry->name_length == name_length &&
  12600.            binaryEqual (entry->name, name, (int)name_length))))
  12601.         break;
  12602.     XauDisposeAuth (entry);
  12603.     }
  12604.     (void) fclose (auth_file);
  12605.     return entry;
  12606. }
  12607.  
  12608. static int
  12609. read_short (shortp, file)
  12610. unsigned short    *shortp;
  12611. FILE        *file;
  12612. {
  12613.     unsigned char   file_short[2];
  12614.  
  12615.     if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
  12616.     return 0;
  12617.     *shortp = file_short[0] * 256 + file_short[1];
  12618.     return 1;
  12619. }
  12620.  
  12621. static int
  12622. read_counted_string (countp, stringp, file)
  12623. unsigned short    *countp;
  12624. char    **stringp;
  12625. FILE    *file;
  12626. {
  12627.     unsigned short  len;
  12628.     char        *data;
  12629.  
  12630.     if (read_short (&len, file) == 0)
  12631.     return 0;
  12632.     if (len == 0) {
  12633.     data = 0;
  12634.     } else {
  12635.         data = malloc ((unsigned) len);
  12636.         if (!data)
  12637.         return 0;
  12638.         if (fread (data, (int) sizeof (char), (int) len, file) != len) {
  12639.         bzero (data, len);
  12640.         free (data);
  12641.         return 0;
  12642.         }
  12643.     }
  12644.     *stringp = data;
  12645.     *countp = len;
  12646.     return 1;
  12647. }
  12648.  
  12649. Xauth *
  12650. XauReadAuth (auth_file)
  12651. FILE    *auth_file;
  12652. {
  12653.     Xauth   local;
  12654.     Xauth   *ret;
  12655.  
  12656.     if (read_short (&local.family, auth_file) == 0)
  12657.     return 0;
  12658.     if (read_counted_string (&local.address_length,
  12659.                  &local.address, auth_file) == 0)
  12660.     return 0;
  12661.     if (read_counted_string (&local.number_length,
  12662.                  &local.number, auth_file) == 0) {
  12663.     if (local.address) free (local.address);
  12664.     return 0;
  12665.     }
  12666.     if (read_counted_string (&local.name_length,
  12667.                  &local.name, auth_file) == 0) {
  12668.     if (local.address) free (local.address);
  12669.     if (local.number) free (local.number);
  12670.     return 0;
  12671.     }
  12672.     if (read_counted_string (&local.data_length,
  12673.                  &local.data, auth_file) == 0) {
  12674.     if (local.address) free (local.address);
  12675.     if (local.number) free (local.number);
  12676.     if (local.name) free (local.name);
  12677.     return 0;
  12678.     }
  12679.     ret = (Xauth *) malloc (sizeof (Xauth));
  12680.     if (!ret) {
  12681.     if (local.address) free (local.address);
  12682.     if (local.number) free (local.number);
  12683.     if (local.name) free (local.name);
  12684.     if (local.data) {
  12685.         bzero (local.data, local.data_length);
  12686.         free (local.data);
  12687.     }
  12688.     return 0;
  12689.     }
  12690.     *ret = local;
  12691.     return ret;
  12692. }
  12693.  
  12694. static int
  12695. write_short (s, file)
  12696. unsigned short    s;
  12697. FILE        *file;
  12698. {
  12699.     unsigned char   file_short[2];
  12700.  
  12701.     file_short[0] = (s & (unsigned)0xff00) >> 8;
  12702.     file_short[1] = s & 0xff;
  12703.     if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
  12704.     return 0;
  12705.     return 1;
  12706. }
  12707.  
  12708. static int
  12709. write_counted_string (count, string, file)
  12710. unsigned short    count;
  12711. char    *string;
  12712. FILE    *file;
  12713. {
  12714.     if (write_short (count, file) == 0)
  12715.     return 0;
  12716.     if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
  12717.     return 0;
  12718.     return 1;
  12719. }
  12720.  
  12721. int
  12722. XauWriteAuth (auth_file, auth)
  12723. FILE    *auth_file;
  12724. Xauth    *auth;
  12725. {
  12726.     if (write_short (auth->family, auth_file) == 0)
  12727.     return 0;
  12728.     if (write_counted_string (auth->address_length,
  12729.                   auth->address, auth_file) == 0)
  12730.     return 0;
  12731.     if (write_counted_string (auth->number_length,
  12732.                   auth->number, auth_file) == 0)
  12733.     return 0;
  12734.     if (write_counted_string (auth->name_length, auth->name, auth_file) == 0)
  12735.     return 0;
  12736.     if (write_counted_string (auth->data_length, auth->data, auth_file) == 0)
  12737.     return 0;
  12738.     return 1;
  12739. }
  12740.  
  12741. #ifdef KRB5
  12742. #ifdef K5_XAUTH
  12743. /*
  12744.  * functions to encode/decode Kerberos V5 principals
  12745.  * into something that can be reasonable spewed over
  12746.  * the wire
  12747.  *
  12748.  * Author: Tom Yu <tlyu@MIT.EDU>
  12749.  *
  12750.  * Still needs to be fixed up wrt signed/unsigned lengths, but we'll worry
  12751.  * about that later.
  12752.  */
  12753.  
  12754. /*
  12755.  * XauKrb5Encode
  12756.  *
  12757.  * this function encodes the principal passed to it in a format that can
  12758.  * easily be dealt with by stuffing it into an X packet.  Encoding is as
  12759.  * follows:
  12760.  *   length count of the realm name
  12761.  *   realm
  12762.  *   component count
  12763.  *   length of component
  12764.  *   actual principal component
  12765.  *   etc....
  12766.  *
  12767.  * Note that this function allocates a hunk of memory, which must be
  12768.  * freed to avoid nasty memory leak type things.  All counts are
  12769.  * byte-swapped if needed. (except for the total length returned)
  12770.  *
  12771.  * nevermind.... stuffing the encoded packet in net byte order just to
  12772.  * always do the right thing.  Don't have to frob with alignment that way.
  12773.  */
  12774. int
  12775. XauKrb5Encode(princ, outbuf)
  12776.     krb5_principal princ;    /* principal to encode */
  12777.     krb5_data *outbuf;        /* output buffer */
  12778. {
  12779.     CARD16 i, numparts, totlen = 0, plen, rlen;
  12780.     char *cp, *pdata;
  12781.  
  12782.     rlen = krb5_princ_realm(princ)->length;
  12783.     numparts = krb5_princ_size(princ);
  12784.     totlen = 2 + rlen + 2;    /* include room for realm length
  12785.                    and component count */
  12786.     for (i = 0; i < numparts; i++)
  12787.     totlen += krb5_princ_component(princ, i)->length + 2;
  12788.     /* add 2 bytes each time for length */
  12789.     if ((outbuf->data = (char *)malloc(totlen)) == NULL)
  12790.     return -1;
  12791.     cp = outbuf->data;
  12792.     *cp++ = (char)((int)(0xff00 & rlen) >> 8);
  12793.     *cp++ = (char)(0x00ff & rlen);
  12794.     memcpy(cp, krb5_princ_realm(princ)->data, rlen);    /* safe */
  12795.     cp += rlen;
  12796.     *cp++ = (char)((int)(0xff00 & numparts) >> 8);
  12797.     *cp++ = (char)(0x00ff & numparts);
  12798.     for (i = 0; i < numparts; i++)
  12799.     {
  12800.     plen = krb5_princ_component(princ, i)->length;
  12801.     pdata = krb5_princ_component(princ, i)->data;
  12802.     *cp++ = (char)((int)(0xff00 & plen) >> 8);
  12803.     *cp++ = (char)(0x00ff & plen);
  12804.     memcpy(cp, pdata, plen);                        /* safe */
  12805.     cp += plen;
  12806.     }
  12807.     outbuf->length = totlen;
  12808.     return 0;
  12809. }
  12810.  
  12811. /*
  12812.  * XauKrb5Decode
  12813.  *
  12814.  * This function essentially reverses what XauKrb5Encode does.
  12815.  * return value: 0 if okay, -1 if malloc fails, -2 if inbuf format bad
  12816.  */
  12817. int
  12818. XauKrb5Decode(inbuf, princ)
  12819.     krb5_data inbuf;
  12820.     krb5_principal *princ;
  12821. {
  12822.     CARD16 i, numparts, plen, rlen;
  12823.     CARD8 *cp, *pdata;
  12824.  
  12825.     if (inbuf.length < 4)
  12826.     {
  12827.     return -2;
  12828.     }
  12829.     *princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
  12830.     if (*princ == NULL)
  12831.     return -1;
  12832.     bzero(*princ, sizeof (krb5_principal_data));
  12833.     cp = (CARD8 *)inbuf.data;
  12834.     rlen = *cp++ << 8;
  12835.     rlen |= *cp++;
  12836.     if (inbuf.length < 4 + (int)rlen + 2)
  12837.     {
  12838.     krb5_free_principal(*princ);
  12839.     return -2;
  12840.     }
  12841.     krb5_princ_realm(*princ)->data = (char *)malloc(rlen);
  12842.     if (krb5_princ_realm(*princ)->data == NULL)
  12843.     {
  12844.     krb5_free_principal(*princ);
  12845.     return -1;
  12846.     }
  12847.     krb5_princ_realm(*princ)->length = rlen;
  12848.     memcpy(krb5_princ_realm(*princ)->data, cp, rlen);   /* safe */
  12849.     cp += rlen;
  12850.     numparts = *cp++ << 8;
  12851.     numparts |= *cp++;
  12852.     krb5_princ_name(*princ) =
  12853.     (krb5_data *)malloc(numparts * sizeof (krb5_data));
  12854.     if (krb5_princ_name(*princ) == NULL)
  12855.     {
  12856.     krb5_free_principal(*princ);
  12857.     return -1;
  12858.     }
  12859.     krb5_princ_size(*princ) = 0;
  12860.     for (i = 0; i < numparts; i++)
  12861.     {
  12862.     if (cp + 2 > (CARD8 *)inbuf.data + inbuf.length)
  12863.     {
  12864.         krb5_free_principal(*princ);
  12865.         return -2;
  12866.     }
  12867.     plen = *cp++ << 8;
  12868.     plen |= *cp++;
  12869.     if (cp + plen > (CARD8 *)inbuf.data + inbuf.length)
  12870.     {
  12871.         krb5_free_principal(*princ);
  12872.         return -2;
  12873.     }
  12874.     pdata = (CARD8 *)malloc(plen);
  12875.     if (pdata == NULL)
  12876.     {
  12877.         krb5_free_principal(*princ);
  12878.         return -1;
  12879.     }
  12880.     krb5_princ_component(*princ, i)->data = (char *)pdata;
  12881.     krb5_princ_component(*princ, i)->length = plen;
  12882.     memcpy(pdata, cp, plen);        /* safe */
  12883.     cp += plen;
  12884.     krb5_princ_size(*princ)++;
  12885.     }
  12886.     return 0;
  12887. }
  12888. #endif /* K5_XAUTH */
  12889. #endif /* KRB5 */
  12890. #endif /* CK_FORWARD_X */
  12891. #endif /* CK_AUTHENTICATION */
  12892.