home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / cku201.zip / ckuath.c < prev    next >
C/C++ Source or Header  |  2002-04-19  |  410KB  |  12,965 lines

  1. char *ckathv = "Authentication, 8.0.210.1, 19 Apr 2002";
  2. /*
  3.   C K U A T H . C  --  Authentication for C-Kermit
  4.  
  5.   Copyright (C) 1999, 2002,
  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. #define CKUATH_C
  43. #include "ckcker.h"
  44. #include "ckucmd.h"                             /* For struct keytab */
  45. #include "ckcnet.h"
  46. #include "ckctel.h"
  47.  
  48. #ifdef CK_SECURITY
  49. char szUserNameRequested[UIDBUFLEN+1];    /* for incoming connections */
  50. char szUserNameAuthenticated[UIDBUFLEN+1];/* for incoming connections */
  51. char szHostName[UIDBUFLEN+1];
  52. char szUserName[UIDBUFLEN+1];
  53. static char szIP[16];
  54. static int  validUser = AUTH_REJECT;    /* User starts out invalid */
  55. int authentication_version = AUTHTYPE_NULL;
  56. int accept_complete = 0;
  57. #endif /* CK_SECURITY */
  58.  
  59. #ifdef CK_AUTHENTICATION
  60. #ifdef CK_SSL
  61. #ifdef KRB5
  62. #define TLS_VERIFY
  63. #endif /* KRB5 */
  64. #endif /* CK_SSL */
  65.  
  66. #ifdef CK_DES
  67. #ifdef CK_SSL
  68. #ifndef LIBDES
  69. #define LIBDES
  70. #endif /* LIBDES */
  71. #endif /* CK_SSL */
  72. #endif /* CK_DES */
  73.  
  74. #ifdef CRYPT_DLL
  75. #ifndef LIBDES
  76. #define LIBDES
  77. #endif /* LIBDES */
  78. #ifdef OS2
  79. #ifdef NT
  80. #include <windows.h>
  81. #else /* NT */
  82. #define INCL_DOSMODULEMGR
  83. #include <os2.h>
  84. #endif /* NT */
  85. #endif /* OS2 */
  86. #endif /* CRYPT_DLL */
  87.  
  88. #ifdef NT
  89. #define KRB5_AUTOCONF__
  90. #define NTLM
  91. #endif /* NT */
  92.  
  93. #ifdef CK_KERBEROS
  94. #define KINIT
  95. #ifndef HEIMDAL
  96. #define KLIST
  97. #define KDESTROY
  98. #endif /* HEIMDAL */
  99. #define CHECKADDRS
  100. #else /* CK_KERBEROS */
  101. #ifdef KRB4
  102. #undef KRB4
  103. #endif /* KRB4 */
  104. #ifdef KRB5
  105. #undef KRB5
  106. #endif /* KRB5 */
  107. #ifdef KRB524
  108. #undef KRB524
  109. #endif /* KRB524 */
  110. #endif /* CK_KERBEROS */
  111.  
  112. #include <stdlib.h>
  113. #include <string.h>
  114. #include <stdio.h>
  115. #include <time.h>
  116. #include <fcntl.h>
  117. #include <malloc.h>
  118. #ifdef OS2
  119. #include <io.h>
  120. #endif /* OS2 */
  121.  
  122. #ifdef KRB5
  123. #ifdef HEIMDAL
  124. #ifdef printf
  125. #define saveprintf printf
  126. #undef printf
  127. #endif /* printf */
  128. #include "krb5.h"
  129. #include "com_err.h"
  130. #ifdef saveprintf
  131. #define printf saveprintf
  132. #endif /* saveprintf */
  133. #else /* HEIMDAL */
  134. #include "krb5.h"
  135. #include "profile.h"
  136. #include "com_err.h"
  137. #ifdef KRB5_GET_INIT_CREDS_OPT_TKT_LIFE
  138. #define KRB5_HAVE_GET_INIT_CREDS
  139. #else
  140. #define krb5_free_unparsed_name(con,val) krb5_xfree((char *)(val))
  141. #endif
  142. #ifndef KRB5_HAVE_GET_INIT_CREDS
  143. #define krb5_free_data_contents(c,v) krb5_xfree((char *)(v)->data)
  144. #endif
  145. #endif /* HEIMDAL */
  146. #ifdef HAVE_PWD_H
  147. #include <pwd.h>
  148. #endif
  149. #endif /* KRB5 */
  150.  
  151. #ifdef KRB4
  152. #define  des_cblock Block
  153. #define  const_des_cblock const Block
  154. #define  des_key_schedule Schedule
  155. #ifdef KRB524
  156. #ifdef NT
  157. #define _WINDOWS
  158. #endif /* NT */
  159. #include "kerberosIV/krb.h"
  160. #ifndef OS2
  161. _PROTOTYP(const char * krb_get_err_text_entry, (int));
  162. #endif /* OS2 */
  163. #else /* KRB524 */
  164. #ifdef SOLARIS
  165. #ifndef sun
  166. /* for some reason the Makefile entries for the Solaris systems have -Usun */
  167. #define sun
  168. #endif /* sun */
  169. #endif /* SOLARIS */
  170. #include "krb.h"
  171. #define krb_get_err_text_entry krb_get_err_text
  172. #endif /* KRB524 */
  173. #else /* KRB4 */
  174. #ifdef CK_SSL
  175. #define  des_cblock Block
  176. #ifdef COMMENT
  177. #define  const_des_cblock const Block
  178. #endif /* COMMENT */
  179. #define  des_key_schedule Schedule
  180. #endif /* CK_SSL */
  181. #endif /* KRB4 */
  182.  
  183. #include "ckuath.h"
  184. #ifdef CK_KERBEROS
  185. #ifndef KRB5
  186. #define NOBLOCKDEF
  187. #else /* KRB5 */
  188. #ifdef KRB524
  189. #define NOBLOCKDEF
  190. #endif /* KRB524 */
  191. #endif /* KRB5 */
  192. #endif /* CK_KERBEROS */
  193. #include "ckuat2.h"
  194.  
  195. #ifdef CK_SSL
  196. #ifdef LIBDES
  197. #ifndef HEADER_DES_H
  198. #define HEADER_DES_H
  199. #endif /* HEADER_DES_H */
  200. #endif /* LIBDES */
  201. #include "ck_ssl.h"
  202. extern int ssl_finished_messages;
  203. #endif /* SSL */
  204.  
  205. #define PWD_SZ 128
  206.  
  207. #ifndef LIBDES
  208. #ifdef UNIX
  209. #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
  210. #endif /* UNIX */
  211. #else /* LIBDES */
  212. #define des_fixup_key_parity des_set_odd_parity
  213. #endif /* LIBDES */
  214.  
  215. #ifdef OS2
  216. #define MAP_DES
  217. #ifdef KRB4
  218. #define MAP_KRB4
  219. #endif /* KRB4 */
  220. #ifdef SRPDLL
  221. #define MAP_SRP
  222. #endif /* SRPDLL */
  223. #ifdef KRB5
  224. #define MAP_KRB5
  225. #endif /* KRB5 */
  226. #ifdef CRYPT_DLL
  227. #define MAP_CRYPT
  228. #endif /* CRYPT_DLL */
  229. #define MAP_NTLM
  230. #include "ckoath.h"
  231. #include "ckosyn.h"
  232. #endif /* OS2 */
  233.  
  234. /*
  235.  * Globals
  236.  */
  237. int auth_type_user[AUTHTYPLSTSZ] = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
  238. int auth_how=0;
  239. int auth_crypt=0;
  240. int auth_fwd=0;
  241.  
  242. /* These are state completion variables */
  243. static int mutual_complete = 0;
  244.  
  245. #ifdef KRB4
  246. #ifdef OS2
  247. static LEASH_CREDENTIALS cred;
  248. #else /* OS2 */
  249. static CREDENTIALS cred;
  250. #endif /* OS2 */
  251. static KTEXT_ST k4_auth;
  252. static char     k4_name[ANAME_SZ];
  253. static AUTH_DAT k4_adat  = { 0 };
  254. static MSG_DAT  k4_msg_data;
  255. #ifdef CK_ENCRYPTION
  256. static Block    k4_session_key     = { 0 };
  257. static Schedule k4_sched;
  258. static Block    k4_challenge       = { 0 };
  259. #ifdef MIT_CURRENT
  260. static krb5_keyblock k4_krbkey;
  261. #endif /* MIT_CURRENT */
  262. #endif /* ENCRYPTION */
  263. #define KRB4_SERVICE_NAME    "rcmd"
  264.  
  265. _PROTOTYP(static int k4_auth_send,(VOID));
  266. _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
  267. _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
  268. #endif /* KRB4 */
  269.  
  270. #ifdef KRB5
  271. static krb5_data          k5_auth;
  272. static krb5_auth_context  auth_context;
  273. static krb5_keyblock     *k5_session_key = NULL;
  274. static krb5_ticket       *k5_ticket = NULL;
  275. #ifndef KRB5_SERVICE_NAME
  276. #define KRB5_SERVICE_NAME    "host"
  277. #endif
  278.  
  279. _PROTOTYP(static int k5_auth_send,(int,int,int));
  280. _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
  281. _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
  282. _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
  283. #ifdef TLS_VERIFY
  284. static int krb5_tls_verified = 0;
  285. #endif /* TLS_VERIFY */
  286. #endif /* KRB5 */
  287.  
  288. #ifdef GSSAPI_KRB5
  289. #include <gssapi/gssapi.h>
  290. #include <gssapi/gssapi_generic.h>
  291. #include <gssapi/gssapi_krb5.h>
  292.  
  293. static gss_ctx_id_t gcontext;
  294. #define GSS_BUFSIZ 4096
  295. static gss_buffer_desc gss_send_tok, gss_recv_tok, *gss_token_ptr;
  296. static char gss_stbuf[GSS_BUFSIZ];
  297. static gss_name_t gss_target_name;
  298. static struct gss_channel_bindings_struct gss_chan;
  299.  
  300. _PROTOTYP(static int gssk5_auth_send,(int,int,int));
  301. _PROTOTYP(static int gssk5_auth_reply,(int, unsigned char *, int));
  302. _PROTOTYP(static int gssk5_auth_is,(int,unsigned char *, int));
  303. _PROTOTYP(static int SendGSSK5AuthSB,(int, void *, int));
  304. #endif /* GSSAPI_KRB5 */
  305.  
  306. #ifdef CK_SRP
  307. #ifdef PRE_SRP_1_7_3
  308. _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
  309. _PROTOTYP(static int srp_is,(int, unsigned char *, int));
  310. #else /* PRE_SRP_1_7_3 */
  311. _PROTOTYP(static int new_srp_reply,(int, unsigned char *, int));
  312. _PROTOTYP(static int new_srp_is,(int, unsigned char *, int));
  313. #endif /* PRE_SRP_1_7_3 */
  314. #endif /* SRP */
  315.  
  316. _PROTOTYP(void auth_finished, (int));
  317.  
  318. #ifdef CK_ENCRYPTION
  319. int encrypt_flag = 1;
  320. #endif
  321. #ifdef FORWARD
  322. int forward_flag = 0;              /* forward tickets? */
  323. int forwardable_flag = 1;          /* get forwardable tickets to forward? */
  324. int forwarded_tickets = 0;         /* were tickets forwarded? */
  325. #endif
  326.  
  327. static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  328.                                         AUTHTYPE_KERBEROS_V5, };
  329. #define AUTHTMPBL 2048
  330. static char strTmp[AUTHTMPBL+1];
  331. static char szLocalHostName[UIDBUFLEN+1];
  332. static kstream g_kstream=NULL;
  333.  
  334. #ifdef KRB5
  335. krb5_context k5_context=NULL;
  336. static krb5_creds * ret_cred=NULL;
  337. static krb5_context telnet_context=NULL;
  338. static char * telnet_krb5_realm = NULL;
  339. static krb5_principal fwd_server = NULL;
  340. #endif /* KRB5 */
  341.  
  342. #ifdef CK_SRP
  343. #ifdef PRE_SRP_1_4_4
  344. #ifndef PRE_SRP_1_4_5
  345. #define PRE_SRP_1_4_5
  346. #endif /* PRE_SRP_1_4_5 */
  347. #endif /* PRE_SRP_1_4_5 */
  348. #ifdef PRE_SRP_1_4_5
  349. #ifndef PRE_SRP_1_7_3
  350. #define PRE_SRP_1_7_3
  351. #endif /* PRE_SRP_1_7_3 */
  352. #endif /* PRE_SRP_1_4_5 */
  353. #include <t_pwd.h>
  354. #include <t_client.h>
  355. #include <t_server.h>
  356. static struct t_server * ts = NULL;
  357. static struct t_client * tc = NULL;
  358. #ifdef PRE_SRP_1_4_4
  359. static struct t_pw * tpw = NULL;
  360. static struct t_conf * tconf = NULL;
  361. #endif /* PRE_SRP_1_4_4 */
  362. #ifndef PRE_SRP_1_7_3
  363. #ifndef STDC_HEADERS
  364. #define STDC_HEADERS 1
  365. #endif /* STDC_HEADERS */
  366. #include <srp.h>
  367. static SRP * s_srp = NULL;
  368. static cstr * s_key = NULL;
  369. static SRP * c_srp = NULL;
  370. static cstr * c_key = NULL;
  371. #endif /* PRE_SRP_1_7_3 */
  372. static int srp_waitresp = 0;    /* Flag to indicate readiness for response */
  373. static char srp_passwd[PWD_SZ];
  374. #endif /* CK_SRP */
  375.  
  376. #ifdef CK_KERBEROS
  377. #ifdef RLOGCODE
  378. #define OPTS_FORWARD_CREDS           0x00000020
  379. #define OPTS_FORWARDABLE_CREDS       0x00000010
  380. #define KCMD_KEYUSAGE                1026
  381.  
  382. #define RLOG_BUFSIZ 5120
  383. static int rlog_encrypt = 0;
  384. char des_inbuf[2*RLOG_BUFSIZ];       /* needs to be > largest read size */
  385. char des_outpkt[2*RLOG_BUFSIZ+4];    /* needs to be > largest write size */
  386. #ifdef KRB5
  387. krb5_data desinbuf,desoutbuf;
  388. krb5_encrypt_block eblock;             /* eblock for encrypt/decrypt */
  389. static krb5_data encivec_i, encivec_o;
  390. #endif /* KRB5 */
  391. #endif /* RLOGCODE */
  392. static char storage[65536];            /* storage for the decryption */
  393. static int nstored = 0;
  394. static char *store_ptr = storage;
  395.  
  396. extern char * krb5_d_principal;         /* Default principal */
  397. extern char * krb5_d_instance;          /* Default instance */
  398. extern char * krb5_d_realm;             /* Default realm */
  399. extern char * krb5_d_cc;                /* Default credentials cache */
  400. extern char * krb5_d_srv;               /* Default service name */
  401. extern int    krb5_d_lifetime;          /* Default lifetime */
  402. extern int    krb5_d_forwardable;
  403. extern int    krb5_d_proxiable;
  404. extern int    krb5_d_renewable;
  405. extern int    krb5_autoget;
  406. extern int    krb5_checkaddrs;
  407. extern int    krb5_d_getk4;
  408. extern int    krb5_d_no_addresses;
  409. extern char * k5_keytab;
  410.  
  411. extern int    krb5_errno;
  412. extern char * krb5_errmsg;
  413.  
  414. extern char * krb4_d_principal;         /* Default principal */
  415. extern char * krb4_d_realm;             /* Default realm */
  416. extern char * krb4_d_srv;               /* Default service name */
  417. extern int    krb4_d_lifetime;          /* Default lifetime */
  418. extern int    krb4_d_preauth;
  419. extern char * krb4_d_instance;
  420. extern int    krb4_autoget;
  421. extern int    krb4_checkaddrs;
  422. extern char * k4_keytab;
  423.  
  424. extern int    krb4_errno;
  425. extern char * krb4_errmsg;
  426. #endif /* CK_KERBEROS */
  427.  
  428. extern char tn_msg[], hexbuf[];         /* from ckcnet.c */
  429. extern char pwbuf[];
  430. extern int  pwflg, pwcrypt;
  431. extern int deblog, debses, tn_deb;
  432. extern int sstelnet, inserver;
  433. #ifdef CK_LOGIN
  434. extern int ckxanon;
  435. #endif /* CK_LOGIN */
  436. extern int tn_auth_how;
  437. extern int tn_auth_enc;
  438. #ifdef CK_ENCRYPTION
  439. extern int cx_type;
  440. #endif /* CK_ENCRYPTION */
  441. extern int quiet, ttyfd;
  442.  
  443. int
  444. ck_gssapi_is_installed()
  445. {
  446. #ifdef KRB5
  447. #ifdef OS2
  448.     return(hGSSAPI != NULL);
  449. #else /* OS2 */
  450.     return(1);
  451. #endif /* OS2 */
  452. #else /* KRB5 */
  453.     return(0);
  454. #endif /* KRB5 */
  455. }
  456.  
  457. int
  458. ck_krb5_is_installed()
  459. {
  460. #ifdef KRB5
  461. #ifdef OS2
  462.     return(hKRB5_32 != NULL);
  463. #else /* OS2 */
  464.     return(1);
  465. #endif /* OS2 */
  466. #else /* KRB5 */
  467.     return(0);
  468. #endif /* KRB5 */
  469. }
  470.  
  471.  
  472. int
  473. ck_krb5_is_installed_as_server()
  474. {
  475. #ifdef KRB5
  476. #ifdef HEIMDAL
  477.     krb5_error_code ret;
  478.     krb5_keytab kt;
  479.     krb5_kt_cursor cursor;
  480.  
  481.     ret = krb5_kt_default(k5_context, &kt);
  482.     if ( ret ) {
  483.         krb5_kt_close(k5_context, kt);
  484.         return(0);
  485.     } else {
  486.         krb5_kt_end_seq_get(k5_context, kt, &cursor);
  487.         krb5_kt_close(k5_context, kt);
  488.         return(1);
  489.     }
  490. #else /* HEIMDAL */
  491. #ifndef COMMENT
  492.     char ktname[CKMAXPATH]="";
  493.  
  494.     if ( k5_keytab ) {
  495.         ckstrncpy(ktname,k5_keytab,CKMAXPATH);
  496.     } else {
  497.         krb5_error_code code;
  498.  
  499.         if ( k5_context == NULL)
  500.             if (krb5_init_context(&k5_context))
  501.                 return(0);
  502.  
  503.         code = krb5_kt_default_name(k5_context,ktname,CKMAXPATH);
  504.         debug(F101,"krb5_kt_default_name","",code);
  505.         if ( code ) {
  506.             /* We can't check the existence of the file since we can't   */
  507.             /* determine the file name.  So we return TRUE and let       */
  508.             /* Krb5 be offered to the user even though it may fail later */
  509.             return(1);
  510.         }
  511.     }
  512.  
  513.     if ( !strncmp("FILE:",ktname,5) ) {
  514.         if ( zchki(&ktname[5]) > 0 )
  515.             return(1);
  516.         else
  517.             return(0);
  518.     } else {
  519.         if (ktname[0])
  520.             return(1);
  521.         else
  522.             return(0);
  523.     }
  524. #else /* COMMENT */
  525.     krb5_error_code             krb5rc = KRB5KRB_ERR_GENERIC;
  526.     krb5_context                krb5context = NULL;
  527.     krb5_ccache                 krb5ccdef = NULL;
  528.     krb5_creds                  krb5creds, *krb5credsp = NULL;
  529.     int                         rc = 0;
  530.  
  531.     if ( !ck_krb5_is_installed() )
  532.         return(0);
  533.  
  534.     memset((char *)&krb5creds, 0, sizeof(krb5creds));
  535.  
  536.     if ((krb5rc = krb5_init_context(&krb5context)) != 0)
  537.         goto err;
  538.  
  539.     if ((krb5rc = krb5_sname_to_principal(krb5context,
  540.                                           szHostName,
  541.                                           krb5_d_srv ?
  542.                                           krb5_d_srv :
  543.                                           KRB5_SERVICE_NAME,
  544.                                           KRB5_NT_SRV_HST,
  545.                                           &krb5creds.server)) != 0)
  546.       goto err;
  547.  
  548.     if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0)
  549.         goto err;
  550.  
  551.     if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef,
  552.                                          &krb5creds.client)) != 0)
  553.         goto err;
  554.  
  555.     if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef,
  556.                                         &krb5creds, &krb5credsp)) != 0)
  557.         goto err;
  558.     rc = 1;
  559.  
  560.   err:
  561.  
  562.     if (krb5creds.client)
  563.       krb5_free_principal(krb5context, krb5creds.client);
  564.     if (krb5creds.server)
  565.       krb5_free_principal(krb5context, krb5creds.server);
  566.     if (krb5context)
  567.       krb5_free_context(krb5context);
  568.     return(rc);
  569.  
  570. #endif /* COMMENT */
  571. #endif /* HEIMDAL */
  572. #else /* KRB5 */
  573.     return(0);
  574. #endif /* KRB5 */
  575. }
  576.  
  577. int
  578. ck_krb4_is_installed()
  579. {
  580. #ifdef KRB4
  581. #ifdef OS2
  582.     return(hKRB4_32 != NULL);
  583. #else /* OS2 */
  584.     return(1);
  585. #endif /* OS2 */
  586. #else /* KRB4 */
  587.     return(0);
  588. #endif /* KRB4 */
  589. }
  590.  
  591. int
  592. ck_krb4_is_installed_as_server()
  593. {
  594.     if ( !ck_krb4_is_installed() )
  595.         return(0);
  596.  
  597. #ifdef KRB4
  598.     if ( !k4_keytab ) {
  599. #ifdef NT
  600.         char name[CKMAXPATH]="";
  601.         DWORD len = CKMAXPATH;
  602.  
  603.         len = GetWindowsDirectory(name,len);
  604.         if ( len > 0 )
  605.             ckstrncat(name,"/srvtab",CKMAXPATH);
  606.         if ( name[0] )
  607.             makestr(&k4_keytab,name);
  608. #else /* NT */
  609.         makestr(&k4_keytab,"/etc/srvtab");
  610. #endif /* NT */
  611.     }
  612.  
  613.     if ( !k4_keytab )
  614.         return(0);
  615.  
  616.     if ( zchki(k4_keytab) > 0 )
  617.         return(1);
  618. #ifdef KRB524
  619.     else if (ck_krb5_is_installed_as_server())
  620.         return(1);
  621. #endif /* KRB524 */
  622.     else
  623.         return(0);
  624. #endif /* KRB4 */
  625. }
  626.  
  627. int
  628. ck_srp_is_installed_as_server()
  629. {
  630. #ifdef CK_SRP
  631. #ifdef SRPDLL
  632.     if ( hSRP == NULL )
  633.         return(0);
  634. #endif /* SRPDLL */
  635. #ifndef PRE_SRP_1_7_3
  636.     {
  637.         SRP * s_srp = SRP_new(SRP_RFC2945_server_method());
  638.         if ( s_srp ) {
  639.             SRP_free(s_srp);
  640.             s_srp = NULL;
  641.             return(1);
  642.         }
  643.         return(0);
  644.     }
  645. #else /* PRE_SRP_1_7_3 */
  646.     {
  647.         struct t_pw * tpw = NULL;
  648.         struct t_conf * tconf = NULL;
  649.         if((tconf = t_openconf(NULL)) == NULL)
  650.             return(0);
  651.         if((tpw = t_openpw(NULL)) == NULL) {
  652.             t_closeconf(tconf);
  653.             return(0);
  654.         }
  655.         t_closeconf(tconf);
  656.         t_closepw(tpw);
  657.         return(1);
  658.     }
  659. #endif /* PRE_SRP_1_7_3 */
  660. #else /* SRP */
  661.     return(0);
  662. #endif /* SRP */
  663. }
  664.  
  665. int
  666. ck_srp_is_installed()
  667. {
  668. #ifdef CK_SRP
  669. #ifdef SRPDLL
  670.     if ( hSRP == NULL )
  671.         return(0);
  672. #endif /* SRPDLL */
  673.     return(1);
  674. #else /* CK_SRP */
  675.     return(0);
  676. #endif /* CK_SRP */
  677. }
  678.  
  679. int
  680. ck_krypto_is_installed()
  681. {
  682. #ifdef CK_SRP
  683. #ifdef OS2
  684.     if ( hLIBKRYPTO == NULL )
  685.         return(0);
  686. #endif /* OS2 */
  687.     return(1);
  688. #else /* CK_SRP */
  689.     return(0);
  690. #endif /* CK_SRP */
  691. }
  692.  
  693. int
  694. ck_crypt_is_installed()
  695. {
  696. #ifdef CK_ENCRYPTION
  697. #ifdef CRYPT_DLL
  698.     return(hCRYPT != NULL);
  699. #else /* CRYPT_DLL */
  700.     return(1);
  701. #endif /* CRYPT_DLL */
  702. #else /* ENCRYPTION */
  703.     return(0);
  704. #endif /* ENCRYPTION */
  705. }
  706.  
  707. int
  708. ck_ntlm_is_installed()
  709. {
  710. #ifdef NT
  711.     return(hSSPI != NULL);
  712. #else /* NT */
  713.     return(0);
  714. #endif /* NT */
  715. }
  716.  
  717. int
  718. ck_tn_auth_valid()
  719. {
  720.     return(validUser);
  721. }
  722.  
  723. /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
  724.  *
  725.  * Is an authentication negotiation still in progress?
  726.  *
  727.  */
  728.  
  729. int
  730. #ifdef CK_ANSIC
  731. ck_tn_auth_in_progress(void)
  732. #else
  733. ck_tn_auth_in_progress()
  734. #endif
  735. {
  736.     switch (authentication_version) {
  737.     case AUTHTYPE_AUTO:
  738.         return(1);
  739.     case AUTHTYPE_NULL:
  740.         return(0);
  741. #ifdef KRB4
  742.     case AUTHTYPE_KERBEROS_V4:
  743.         if (!accept_complete) {
  744.             debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
  745.                    "",0);
  746.             return(1);
  747.         }
  748.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  749.             debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
  750.                    "",0);
  751.             return(1);
  752.         }
  753.         else
  754.             return(0);
  755. #endif /* KRB4 */
  756. #ifdef KRB5
  757.     case AUTHTYPE_KERBEROS_V5:
  758.         if (!accept_complete) {
  759.             debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
  760.                    "",0);
  761.             return(1);
  762.         }
  763.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  764.             debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
  765.                    "",0);
  766.             return(1);
  767.         }
  768.         else
  769.             return(0);
  770. #ifdef GSSAPI_K5
  771.     case AUTHTYPE_GSSAPI_KRB5:
  772.         if (!accept_complete) {
  773.             debug(F100,"ck_auth_in_progress() GSSAPI Kerberos 5 !accept_complete",
  774.                    "",0);
  775.             return(1);
  776.         }
  777.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  778.             debug(F100,"ck_auth_in_progress() GSSAPI Kerberos 5 !mutual_complete",
  779.                    "",0);
  780.             return(1);
  781.         }
  782.         else
  783.             return(0);
  784.         break;
  785. #endif /* GSSAPI_K5 */
  786. #endif /* KRB5 */
  787. #ifdef CK_SRP
  788.     case AUTHTYPE_SRP:
  789.         if (!accept_complete || srp_waitresp)
  790.             return(1);
  791.         else
  792.             return(0);
  793. #endif /* CK_SRP */
  794. #ifdef NTLM
  795.     case AUTHTYPE_NTLM:
  796.         if (!accept_complete) {
  797.             debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
  798.                    "",0);
  799.             return(1);
  800.         }
  801.         else
  802.             return(0);
  803. #endif /* NTLM */
  804.     case AUTHTYPE_SSL:
  805.         if (!accept_complete) {
  806.             debug(F100,"ck_auth_in_progress() SSL !accept_complete",
  807.                    "",0);
  808.             return(1);
  809.         }
  810.         else
  811.             return(0);
  812.     default:
  813.         return(0);
  814.     }
  815.     return(0);
  816. }
  817.  
  818.  
  819. /*  C K _ K R B _ T N _ A U T H _ R E Q U E S T
  820.  *
  821.  *  Builds a Telnet Authentication Send Negotiation providing the
  822.  *  list of supported authentication methods.  To be used only
  823.  *  when accepting incoming connections as only the server (DO) side of the
  824.  *  Telnet negotiation is allowed to send an AUTH SEND.
  825.  *
  826.  *  Returns: 0 on success and -1 on failure
  827.  */
  828.  
  829. static unsigned char str_request[64] = { IAC, SB,
  830.                                              TELOPT_AUTHENTICATION,
  831.                                              TELQUAL_SEND };
  832. #ifdef GSSAPI_K5
  833. static int
  834. ck_tn_auth_request_gsskrb5(int i)
  835. {
  836.     if (ck_gssapi_is_installed() && ck_krb5_is_installed_as_server()) {
  837.         if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
  838.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  839.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  840.                tn_auth_enc == TN_AUTH_ENC_EXCH) ) {
  841.             str_request[i++] = AUTHTYPE_KERBEROS_V5;
  842.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  843.             str_request[i] |= AUTH_ENCRYPT_AFTER_EXCHANGE;
  844.  
  845.             if ( deblog || tn_deb || debses )
  846.                 ckstrncat(tn_msg,
  847.                 "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_AFTER_EXCHANGE ",
  848.                           TN_MSG_LEN);
  849.             i++;
  850.         }
  851.     }
  852. }
  853. #endif /* GSSAPI_K5 */
  854.  
  855. #ifdef KRB5
  856. static int
  857. ck_tn_auth_request_krb5(int i)
  858. {
  859.     if (ck_krb5_is_installed_as_server()) {
  860. #ifdef CK_SSL
  861.         if ( ck_ssleay_is_installed() &&
  862.              (tls_active_flag || ssl_active_flag) &&
  863.              ssl_finished_messages )
  864.         {
  865. #ifdef USE_INI_CRED_FWD
  866.             if ( forward_flag &&
  867.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  868.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  869.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  870.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  871.                  )
  872.             {
  873.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  874.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  875.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  876.                 str_request[i] |= INI_CRED_FWD_ON;
  877.  
  878.                 if ( deblog || tn_deb || debses )
  879.                     ckstrncat(tn_msg,
  880.  "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS|INI_CRED_FWD_ON ",
  881.                                TN_MSG_LEN);
  882.                 i++;
  883.             }
  884. #endif /* USE_INI_CRED_FWD */
  885.             if ( (tn_auth_how == TN_AUTH_HOW_ANY ||
  886.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  887.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  888.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  889.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  890.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  891.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  892.  
  893.                 if ( deblog || tn_deb || debses )
  894.                     ckstrncat(tn_msg,
  895.                       "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_START_TLS ",
  896.                               TN_MSG_LEN);
  897.                 i++;
  898.             }
  899.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  900.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  901.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  902.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  903.                 str_request[i] |= AUTH_ENCRYPT_START_TLS;
  904.  
  905.                 if ( deblog || tn_deb || debses )
  906.                     ckstrncat(tn_msg,
  907.                     "KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
  908.                                TN_MSG_LEN);
  909.                 i++;
  910.             }
  911.         }
  912. #ifdef CK_ENCRYPTION
  913.         else
  914.         {
  915. #endif /* CK_ENCRYPTION */
  916. #endif /* CK_SSL */
  917. #ifdef CK_ENCRYPTION
  918. #ifdef USE_INI_CRED_FWD
  919.             if ( forward_flag &&
  920.                  TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  921.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  922.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  923.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  924.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  925.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  926.                  )
  927.             {
  928.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  929.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  930.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  931.                 str_request[i] |= INI_CRED_FWD_ON;
  932.  
  933.                 if ( deblog || tn_deb || debses )
  934.                     ckstrncat(tn_msg,
  935.   "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT|INI_CRED_FWD_ON ",
  936.                                TN_MSG_LEN);
  937.                 i++;
  938.             }
  939. #endif /* USE_INI_CRED_FWD */
  940.  
  941.             if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  942.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  943.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  944.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  945.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  946.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  947.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  948.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  949.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  950.  
  951.                 if ( deblog || tn_deb || debses )
  952.                     ckstrncat(tn_msg,
  953.               "KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT_USING_TELOPT ",
  954.                                TN_MSG_LEN);
  955.                 i++;
  956.             }
  957. #ifdef CK_SSL
  958.         }
  959. #endif /* CK_SSL */
  960. #endif /* CK_ENCRYPTION */
  961.  
  962.         if ( TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  963.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  964.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  965.                tn_auth_enc == TN_AUTH_ENC_NONE)
  966. #ifdef CK_SSL
  967.              && !(ck_ssleay_is_installed() &&
  968.                    (tls_active_flag || ssl_active_flag) &&
  969.                    tls_is_anon(0))
  970. #endif /* CK_SSL */
  971.              )
  972.         {
  973. #ifdef CK_ENCRYPTION
  974.             /* Can't perform mutual authentication without encryption */
  975.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  976.                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  977.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  978.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  979.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  980.  
  981.                 if ( deblog || tn_deb || debses )
  982.                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ",
  983.                                TN_MSG_LEN);
  984.                 i++;
  985.             }
  986. #endif /* CK_ENCRYPTION */
  987.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  988.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  989.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  990.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  991.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  992.  
  993.                 if ( deblog || tn_deb || debses )
  994.                     ckstrncat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ",
  995.                                TN_MSG_LEN);
  996.                 i++;
  997.             }
  998.         }
  999.     }
  1000.     return(i);
  1001. }
  1002. #endif /* KRB5 */
  1003. #ifdef KRB4
  1004. static int
  1005. ck_tn_auth_request_krb4(int i)
  1006. {
  1007.     if (ck_krb4_is_installed_as_server()) {
  1008. #ifdef CK_ENCRYPTION
  1009.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1010.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1011.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1012.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1013.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1014.                tn_auth_enc == TN_AUTH_ENC_TELOPT) )
  1015.         {
  1016.             str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1017.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1018.             str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1019.  
  1020.             if ( deblog || tn_deb || debses )
  1021.               ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ",
  1022.                         TN_MSG_LEN);
  1023.             i++;
  1024.         }
  1025. #endif /* CK_ENCRYPTION */
  1026.  
  1027.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1028.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1029.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1030.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1031.         {
  1032. #ifdef CK_ENCRYPTION
  1033.             /* Can't perform mutual authentication without encryption */
  1034.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1035.                  tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1036.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1037.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1038.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1039.  
  1040.                 if ( deblog || tn_deb || debses )
  1041.                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ",
  1042.                                TN_MSG_LEN);
  1043.                 i++;
  1044.             }
  1045. #endif /* CK_ENCRYPTION */
  1046.             if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1047.                  tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1048.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1049.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1050.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  1051.  
  1052.                 if ( deblog || tn_deb || debses )
  1053.                     ckstrncat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ",
  1054.                                TN_MSG_LEN);
  1055.                 i++;
  1056.             }
  1057.         }
  1058.     }
  1059.  
  1060.     return(i);
  1061. }
  1062. #endif /* KRB4 */
  1063.  
  1064. #ifdef CK_SRP
  1065. static int
  1066. ck_tn_auth_request_srp(int i)
  1067. {
  1068.     if (ck_srp_is_installed_as_server()) {
  1069. #ifndef PRE_SRP_1_4_5
  1070.         /* Dont' do this yet.  SRP when it uses the ENCRYPT_USING_TELOPT   */
  1071.         /* flag it must perform a checksum of the auth-type-pair but there */
  1072.         /* is no mechansim to do that yet.                                 */
  1073. #ifdef CK_SSL
  1074.         if ( ck_ssleay_is_installed() &&
  1075.              (tls_active_flag || ssl_active_flag) &&
  1076.              ssl_finished_messages &&
  1077.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1078.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1079.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1080.                    tn_auth_enc == TN_AUTH_ENC_TELOPT))
  1081.         {
  1082.             str_request[i++] = AUTHTYPE_SRP;
  1083.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1084.             str_request[i] |= AUTH_ENCRYPT_START_TLS;
  1085.  
  1086.             if ( deblog || tn_deb || debses )
  1087.                 ckstrncat(tn_msg,
  1088.                            "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_START_TLS ",
  1089.                            TN_MSG_LEN);
  1090.             i++;
  1091.         }
  1092. #ifdef CK_ENCRYPTION
  1093.         else {
  1094. #endif /* CK_ENCRYPTION */
  1095. #endif /* CK_SSL */
  1096. #ifdef CK_ENCRYPTION
  1097.             if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1098.                  TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1099.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1100.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1101.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1102.                    tn_auth_enc == TN_AUTH_ENC_TELOPT)
  1103.                  ) {
  1104.                 str_request[i++] = AUTHTYPE_SRP;
  1105.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1106.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1107.  
  1108.                 if ( deblog || tn_deb || debses )
  1109.                     ckstrncat(tn_msg,
  1110.                     "SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT_USING_TELOPT ",
  1111.                                TN_MSG_LEN);
  1112.                 i++;
  1113.             }
  1114. #ifdef CK_SSL
  1115.         }
  1116. #endif /* CK_SSL */
  1117. #endif /* CK_ENCRYPTION */
  1118. #endif /* PRE_SRP_1_4_5 */
  1119.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1120.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1121.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1122.                tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1123.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1124.                tn_auth_enc == TN_AUTH_ENC_NONE)
  1125. #ifdef CK_SSL
  1126.              && !(ck_ssleay_is_installed() &&
  1127.                    (tls_active_flag || ssl_active_flag) &&
  1128.                    tls_is_anon(0))
  1129. #endif /* CK_SSL */
  1130.              )
  1131.         {
  1132.             str_request[i++] = AUTHTYPE_SRP;
  1133.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1134.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1135.  
  1136.             if ( deblog || tn_deb || debses )
  1137.                 ckstrncat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ",
  1138.                            TN_MSG_LEN);
  1139.             i++;
  1140.         }
  1141.     }
  1142.  
  1143.     return(i);
  1144. }
  1145. #endif /* CK_SRP */
  1146.  
  1147. #ifdef CK_SSL
  1148. static int
  1149. ck_tn_auth_request_ssl(int i)
  1150. {
  1151.     if (ck_ssleay_is_installed()
  1152.          && !tls_active_flag && !ssl_active_flag && ssl_initialized
  1153.          ) {
  1154.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1155.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1156.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1157.                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1158.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1159.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1160.         {
  1161.             str_request[i++] = AUTHTYPE_SSL;
  1162.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1163.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1164.             if ( deblog || tn_deb || debses )
  1165.                 ckstrncat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ",
  1166.                            TN_MSG_LEN);
  1167.             i++;
  1168.         }
  1169.     }
  1170.  
  1171.     return(i);
  1172. }
  1173. #endif /* CK_SSL */
  1174. #ifdef NTLM
  1175. static int
  1176. ck_tn_auth_request_ntlm(int i)
  1177. {
  1178.     /* Microsoft's Telnet client won't perform authentication if */
  1179.     /* NTLM is not first.                                        */
  1180.     if ( ck_ntlm_is_valid(1) ) {
  1181.         if (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1182.              TELOPT_U_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1183.              (tn_auth_how == TN_AUTH_HOW_ANY ||
  1184.                tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  1185.              (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1186.                tn_auth_enc == TN_AUTH_ENC_NONE) )
  1187.         {
  1188.             str_request[i++] = AUTHTYPE_NTLM;
  1189.             str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1190.             str_request[i] |= AUTH_ENCRYPT_OFF;
  1191.             if ( deblog || tn_deb || debses )
  1192.                 ckstrncat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ",
  1193.                            TN_MSG_LEN);
  1194.             i++;
  1195.         }
  1196.     }
  1197.  
  1198.     return(i);
  1199. }
  1200. #endif /* NTLM */
  1201. int
  1202. #ifdef CK_ANSIC
  1203. ck_tn_auth_request(void)
  1204. #else
  1205. ck_tn_auth_request()
  1206. #endif
  1207. {
  1208.     int i = 4, rc = -1;
  1209.  
  1210. #ifdef CK_SSL
  1211.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1212.         return(0);
  1213.     }
  1214. #endif /* CK_SSL */
  1215.  
  1216.     if ( deblog || tn_deb || debses )
  1217.         strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
  1218.  
  1219.     /* Create a list of acceptable Authentication types to send to */
  1220.     /* the client and let it choose find one that we support       */
  1221.  
  1222.     /* For those authentication methods that support Encryption or */
  1223.     /* Credentials Forwarding we must send all of the appropriate  */
  1224.     /* combinations based upon the state of                        */
  1225.     /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag.          */
  1226.  
  1227.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  1228. #ifdef GSSAPI_K5
  1229.         i = ck_tn_auth_request_gsskrb5(i);
  1230. #endif /* GSSAPI_K5 */
  1231. #ifdef KRB5
  1232.         i = ck_tn_auth_request_krb5(i);
  1233. #endif /* KRB5 */
  1234. #ifdef KRB4
  1235.         i = ck_tn_auth_request_krb4(i);
  1236. #endif /* KRB4 */
  1237. #ifdef CK_SRP
  1238.         i = ck_tn_auth_request_srp(i);
  1239. #endif /* SRP */
  1240. #ifdef CK_SSL
  1241.         i = ck_tn_auth_request_ssl(i);
  1242. #endif /* CK_SSL */
  1243. #ifdef NTLM
  1244.         i = ck_tn_auth_request_ntlm(i);
  1245. #endif /* NTLM */
  1246.     } else {
  1247.         int j;
  1248.         for ( j=0;
  1249.               j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
  1250.               j++) {
  1251. #ifdef NTLM
  1252.             if (auth_type_user[j] == AUTHTYPE_NTLM)
  1253.                 i = ck_tn_auth_request_ntlm(i);
  1254. #endif /* NTLM */
  1255. #ifdef CK_SSL
  1256.             if ( auth_type_user[j] == AUTHTYPE_SSL )
  1257.                 i = ck_tn_auth_request_ssl(i);
  1258. #endif /* CK_SSL */
  1259. #ifdef CK_SRP
  1260.             if ( auth_type_user[j] == AUTHTYPE_SRP )
  1261.                 i = ck_tn_auth_request_srp(i);
  1262. #endif /* SRP */
  1263. #ifdef GSSAPI_K5
  1264.             if ( auth_type_user[j] == AUTHTYPE_GSSAPI_KRB5 )
  1265.                 i = ck_tn_auth_request_gsskrb5(i);
  1266. #endif /* GSSAPI_K5 */
  1267. #ifdef KRB5
  1268.             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5 )
  1269.                 i = ck_tn_auth_request_krb5(i);
  1270. #endif /* KRB5 */
  1271. #ifdef KRB4
  1272.             if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4 )
  1273.                 i = ck_tn_auth_request_krb4(i);
  1274. #endif /* KRB4 */
  1275.         }
  1276.     }
  1277.  
  1278.     str_request[i++] = IAC;
  1279.     str_request[i++] = SE;
  1280.     if ( deblog || tn_deb || debses ) {
  1281.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1282.         debug(F100,tn_msg,"",0);
  1283.         if (tn_deb || debses) tn_debug(tn_msg);
  1284.     }
  1285.  
  1286.     /* Send data */
  1287. #ifdef OS2
  1288.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1289. #endif
  1290.     rc = ttol((CHAR *)str_request, i);
  1291. #ifdef OS2
  1292.     ReleaseTelnetMutex();
  1293. #endif
  1294.     if ( rc == i )
  1295.         return(0);
  1296.     else
  1297.         return(-1);
  1298. }
  1299.  
  1300. #ifdef CK_ENCRYPTION
  1301. VOID
  1302. ck_tn_enc_start()
  1303. {
  1304.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1305.         return;
  1306.     if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
  1307.          (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
  1308.         debug(F110,"ck_tn_enc_start","nothing to do",0);
  1309.         return;
  1310.     }
  1311.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1312.     if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
  1313.         debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
  1314.         encrypt_request_start();
  1315.     }
  1316.     if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
  1317.         debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
  1318.         encrypt_send_request_start();
  1319.     }
  1320.     tn_wait("encrypt start");
  1321.     tn_push();
  1322. }
  1323.  
  1324. VOID
  1325. ck_tn_enc_stop()
  1326. {
  1327.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1328.         return;
  1329.     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
  1330.          !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
  1331.         debug(F110,"ck_tn_enc_stop","nothing to do",0);
  1332.       return;
  1333.     }
  1334.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1335.     if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
  1336.         debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
  1337.         encrypt_send_request_end();
  1338.     }
  1339.     if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
  1340.         debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
  1341.         encrypt_send_end();
  1342.     }
  1343.     tn_wait("encrypt stop");
  1344.     tn_push();
  1345. }
  1346. #endif /* CK_ENCRYPTION */
  1347.  
  1348. /*  C K _ K R B _ T N _ S B _ A U T H
  1349.  *  An interface between the C-Kermit Telnet Command Parser and the Authent-
  1350.  *  ication option parser implemented in the Kerberos Telnet client.
  1351.  *
  1352.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1353.  *  len  - the length of the buffer
  1354.  *
  1355.  *  Returns: 0 on success and -1 on failure
  1356.  */
  1357.  
  1358. int
  1359. #ifdef CK_ANSIC
  1360. ck_tn_sb_auth(char * sb, int len)
  1361. #else /* CK_ANSIC */
  1362. ck_tn_sb_auth(sb,len) char * sb; int len;
  1363. #endif /* CK_ANSIC */
  1364. {
  1365.     /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1366.     /* and it wants the length to exclude the IAC SE bytes                  */
  1367.     char * buf;
  1368.     int rc = -1;
  1369.  
  1370.     buf = malloc(len-1);
  1371.     if ( !buf ) return(-1);
  1372.  
  1373.     buf[0] = SB;
  1374.     memcpy( &buf[1], sb, len-2 );
  1375.     rc = auth_parse(buf,len-1);
  1376.     free(buf);
  1377.     debug(F111,"ck_tn_sb_auth","rc",rc);
  1378.     if (rc == AUTH_FAILURE) {
  1379.         authentication_version = AUTHTYPE_NULL;
  1380. #ifndef NOLOCAL
  1381. #ifdef OS2
  1382.         ipadl25();
  1383. #endif /* OS2 */
  1384. #endif /* NOLOCAL */
  1385.         return(-1);
  1386.     }
  1387. #ifndef NOLOCAL
  1388. #ifdef OS2
  1389.     ipadl25();
  1390. #endif /* OS2 */
  1391. #endif /* NOLOCAL */
  1392.     return(0);
  1393. }
  1394.  
  1395. /*  C K _ K R B _ T N _ S B _ E N C R Y P T
  1396.  *  An interface between the C-Kermit Telnet Command Parser and the Encryption
  1397.  *  option parser implemented in the Kerberos Telnet client.
  1398.  *
  1399.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1400.  *  len  - the length of the buffer
  1401.  *
  1402.  *  Returns: Always returns 0 for success since encrypt_parse is void
  1403.  */
  1404.  
  1405.  
  1406. int
  1407. #ifdef CK_ANSIC
  1408. ck_tn_sb_encrypt(char * sb, int len)
  1409. #else
  1410. ck_tn_sb_encrypt(sb,len) char * sb; int len;
  1411. #endif /* CK_ANSIC */
  1412. {
  1413.     /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1414.     /* and it wants the length to exclude the IAC SE bytes                  */
  1415. #ifdef CK_ENCRYPTION
  1416.     char * buf;
  1417.     int rc = -1;
  1418.  
  1419.     buf = malloc(len-1);
  1420.     if ( !buf ) return(-1);
  1421.  
  1422.     buf[0] = SB;
  1423.     memcpy( &buf[1], sb, len-2 );
  1424.     rc = encrypt_parse(buf,len-1);
  1425.  
  1426.     if (rc < 0) {
  1427.         free(buf);
  1428.         return(-1);
  1429.     }
  1430.  
  1431.     /* This is a hack.  It does not belong here but should really be in */
  1432.     /* encrypt_parse() but in K95 the encrypt_parse() routine does not  */
  1433.     /* have access to the telopt_states array.                          */
  1434.     if ( buf[1] == ENCRYPT_REQEND )
  1435.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1436.     else if ( buf[1] == ENCRYPT_REQSTART )
  1437.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1438. #ifndef NOLOCAL
  1439. #ifdef OS2
  1440.     ipadl25();
  1441. #endif /* OS2 */
  1442. #endif /* NOLOCAL */
  1443.     free(buf);
  1444. #endif /* ENCRYPTION */
  1445.     return(0);
  1446. }
  1447.  
  1448.  
  1449. /*  C K _ K R B _ E N C R Y P T I N G
  1450.  *  Returns 1 if we are encrypting and 0 if we are not
  1451.  */
  1452.  
  1453. int
  1454. #ifdef CK_ANSIC
  1455. ck_tn_encrypting(VOID)
  1456. #else /* CK_ANSIC */
  1457. ck_tn_encrypting()
  1458. #endif /* CK_ANSIC */
  1459. {
  1460. #ifdef CK_ENCRYPTION
  1461.     if ( g_kstream == NULL )
  1462.         return(0);
  1463.     if ( g_kstream->encrypt && encrypt_is_encrypting()) {
  1464.         debug(F111,"ck_tn_encrypting","encrypting",
  1465.                g_kstream->encrypt_type);
  1466.         return(g_kstream->encrypt_type);
  1467.     }
  1468. #endif /* CK_ENCRYPTION */
  1469.     debug(F110,"ck_tn_encrypting","not encrypting",0);
  1470.     return(0);
  1471. }
  1472.  
  1473. /*  C K _ K R B _ D E C R Y P T I N G
  1474.  *  Returns 1 if we are decrypting and 0 if we are not
  1475.  */
  1476.  
  1477. int
  1478. #ifdef CK_ANSIC
  1479. ck_tn_decrypting(VOID)
  1480. #else
  1481. ck_tn_decrypting()
  1482. #endif /* CK_ANSIC */
  1483. {
  1484. #ifdef CK_ENCRYPTION
  1485.     if ( g_kstream == NULL )
  1486.         return(0);
  1487.     if ( g_kstream->decrypt && encrypt_is_decrypting()) {
  1488.         debug(F111,"ck_tn_decrypting","decrypting",
  1489.                g_kstream->decrypt_type);
  1490.         return(g_kstream->decrypt_type);
  1491.     }
  1492. #endif /* CK_ENCRYPTION */
  1493.     debug(F110,"ck_tn_decrypting","not decrypting",0);
  1494.     return(0);
  1495. }
  1496.  
  1497. /*  C K _ K R B _ A U T H E N T I C A T E D
  1498.  *  Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
  1499.  *  or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
  1500.  */
  1501.  
  1502. int
  1503. #ifdef CK_ANSIC
  1504. ck_tn_authenticated(VOID)
  1505. #else
  1506. ck_tn_authenticated()
  1507. #endif
  1508. {
  1509.     return(authentication_version);
  1510. }
  1511.  
  1512. /*  C K _ K R B _ E N C R Y P T
  1513.  *  encrypts n characters in s if we are encrypting
  1514.  */
  1515.  
  1516. VOID
  1517. #ifdef CK_ANSIC
  1518. ck_tn_encrypt( char * s, int n )
  1519. #else
  1520. ck_tn_encrypt( s,n ) char * s; int n;
  1521. #endif
  1522. {
  1523. #ifdef CK_ENCRYPTION
  1524.     struct kstream_data_block i;
  1525.  
  1526.     if (g_kstream->encrypt && encrypt_is_encrypting()) {
  1527. #ifdef DEBUG
  1528.       hexdump("from plaintext", s, n);
  1529. #endif
  1530.         i.ptr = s;
  1531.         i.length = n;
  1532.         g_kstream->encrypt(&i, NULL);
  1533. #ifdef DEBUG
  1534.         hexdump("to cyphertext", s, n);
  1535. #endif
  1536.     }
  1537.     else debug(F101,"ck_tn_encrypt not encrypting","",n);
  1538. #endif /* ENCRYPTION */
  1539. }
  1540.  
  1541. /*  C K _ K R B _ D E C R Y P T
  1542.  *  decrypts n characters in s if we are decrypting
  1543.  */
  1544.  
  1545. VOID
  1546. #ifdef CK_ANSIC
  1547. ck_tn_decrypt( char * s, int n )
  1548. #else
  1549. ck_tn_decrypt( s,n ) char * s; int n;
  1550. #endif
  1551. {
  1552. #ifdef CK_ENCRYPTION
  1553.     struct kstream_data_block i;
  1554.  
  1555.     if (g_kstream->decrypt && encrypt_is_decrypting()) {
  1556.  
  1557. #ifdef DEBUG
  1558.         hexdump("from cyphertext", s, n);
  1559. #endif
  1560.  
  1561.         i.ptr = s;
  1562.         i.length = n;
  1563.         g_kstream->decrypt(&i, NULL);
  1564. #ifdef DEBUG
  1565.         hexdump("to plaintext", s, n);
  1566. #endif
  1567.     }
  1568.     else debug(F101,"ck_tn_decrypt not decrypting","",n);
  1569. #endif /* ENCRYPTION */
  1570. }
  1571.  
  1572. /*  S E N D K 5 A U T H S B
  1573.  *  Send a Kerberos 5 Authentication Subnegotiation to host and
  1574.  *  output appropriate Telnet Debug messages
  1575.  *
  1576.  *  type - Sub Negotiation type
  1577.  *  data - ptr to buffer containing data
  1578.  *  len  - len of buffer if not NUL terminated
  1579.  *
  1580.  *  returns number of characters sent or error value
  1581.  */
  1582.  
  1583. static int
  1584. #ifdef CK_ANSIC
  1585. SendK5AuthSB(int type, void *data, int len)
  1586. #else
  1587. SendK5AuthSB(type,data,len) int type; void *data; int len;
  1588. #endif
  1589. {
  1590.     int rc;
  1591.     unsigned char *p = str_data + 3;
  1592.     unsigned char *cd = (unsigned char *)data;
  1593.     extern int sstelnet;
  1594.  
  1595. #ifdef CK_SSL
  1596.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1597.         if (ttchk() < 0)
  1598.           return(0);
  1599.         else
  1600.           return(1);
  1601.     }
  1602. #endif /* CK_SSL */
  1603.  
  1604.     if ( type < 0 || type > 7 )         /* Check for invalid values */
  1605.         return(0);
  1606.  
  1607.     if (!cd) {
  1608.         cd = (unsigned char *)"";
  1609.         len = 0;
  1610.     }
  1611.  
  1612.     if (len == -1)                        /* Use strlen() for len */
  1613.         len = strlen((char *)cd);
  1614.  
  1615.     /* Construct Message */
  1616.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1617.     *p++ = AUTHTYPE_KERBEROS_V5;
  1618.     *p = AUTH_CLIENT_TO_SERVER;
  1619.     *p |= auth_how;
  1620. #ifdef CK_ENCRYPTION
  1621.     *p |= auth_crypt;
  1622. #endif
  1623. #ifdef USE_INI_CRED_FWD
  1624.     if (auth_fwd)
  1625.         *p |= INI_CRED_FWD_ON;
  1626. #endif /* USE_INI_CRED_FWD */
  1627.     p++;
  1628.     *p++ = type;
  1629.     while (len-- > 0) {
  1630.         if ((*p++ = *cd++) == IAC)
  1631.             *p++ = IAC;
  1632.     }
  1633.     *p++ = IAC;
  1634.     *p++ = SE;
  1635.  
  1636.     /* Handle Telnet Debugging Messages */
  1637.     if (deblog || tn_deb || debses) {
  1638.         int i;
  1639.         int deblen=p-str_data-2;
  1640.         char *s=NULL;
  1641.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1642.             auth_crypt
  1643. #ifdef USE_INI_CRED_FWD
  1644.               | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  1645. #endif /* USE_INI_CRED_FWD */
  1646.                     ;
  1647.  
  1648.         switch (type) {
  1649.         case 0:
  1650.             s = "AUTH";
  1651.             break;
  1652.         case 1:
  1653.             s = "REJECT";
  1654.             break;
  1655.         case 2:
  1656.             s = "ACCEPT";
  1657.             break;
  1658.         case 3:
  1659.             s = "RESPONSE";
  1660.             break;
  1661.         case 4:
  1662.             s = "FORWARD";
  1663.             break;
  1664.         case 5:
  1665.             s = "FORWARD_ACCEPT";
  1666.             break;
  1667.         case 6:
  1668.             s = "FORWARD_REJECT";
  1669.             break;
  1670.         case 7:
  1671.             s = "TLS_VERIFY";
  1672.                 break;
  1673.         }
  1674.  
  1675.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  1676.                   "TELNET SENT SB ",
  1677.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1678.                  str_data[3] == TELQUAL_IS ? "IS" :
  1679.                  str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"," ",
  1680.                  AUTHTYPE_NAME(authentication_version)," ",
  1681.                  AUTHMODE_NAME(mode)," ",
  1682.                  s," ",NULL);
  1683.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1684.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1685.         debug(F100,tn_msg,"",0);
  1686.         if (tn_deb || debses) tn_debug(tn_msg);
  1687.     }
  1688.  
  1689.     /* Send data */
  1690. #ifdef OS2
  1691.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1692. #endif
  1693.     rc = ttol((CHAR *)str_data, p - str_data);
  1694. #ifdef OS2
  1695.     ReleaseTelnetMutex();
  1696. #endif
  1697.     debug(F111,"SendK5AuthSB","ttol()",rc);
  1698.     return(rc);
  1699. }
  1700.  
  1701. /*  S E N D K 4 A U T H S B
  1702.  *  Send a Kerberos 4 Authentication Subnegotiation to host and
  1703.  *  output appropriate Telnet Debug messages
  1704.  *
  1705.  *  type - Sub Negotiation type
  1706.  *  data - ptr to buffer containing data
  1707.  *  len  - len of buffer if not NUL terminated
  1708.  *
  1709.  *  returns number of characters sent or error value
  1710.  */
  1711.  
  1712. static int
  1713. #ifdef CK_ANSIC
  1714. SendK4AuthSB(int type, void *data, int len)
  1715. #else
  1716. SendK4AuthSB(type,data,len) int type; void *data; int len;
  1717. #endif
  1718. {
  1719.     int rc;
  1720.     unsigned char *p = str_data + 3;
  1721.     unsigned char *cd = (unsigned char *)data;
  1722.     extern int sstelnet;
  1723.     int mode = (auth_how & AUTH_HOW_MASK) |
  1724.         auth_crypt;
  1725.  
  1726.     if ( type < 0 || type > 4 )         /* Check for invalid values */
  1727.         return(0);
  1728.  
  1729. #ifdef CK_SSL
  1730.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1731.         if (ttchk() < 0)
  1732.           return(0);
  1733.         else
  1734.           return(1);
  1735.     }
  1736. #endif /* CK_SSL */
  1737.  
  1738.     if (!cd) {
  1739.         cd = (unsigned char *)"";
  1740.         len = 0;
  1741.     }
  1742.  
  1743.     if (len == -1)                        /* Use strlen() for len */
  1744.         len = strlen((char *)cd);
  1745.  
  1746.  
  1747.     /* Construct Message */
  1748.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1749.     *p++ = AUTHTYPE_KERBEROS_V4;
  1750.     *p = AUTH_CLIENT_TO_SERVER;
  1751.     *p |= mode;
  1752.     p++;
  1753.     *p++ = type;
  1754.     while (len-- > 0) {
  1755.         if ((*p++ = *cd++) == IAC)
  1756.             *p++ = IAC;
  1757.         }
  1758.     *p++ = IAC;
  1759.     *p++ = SE;
  1760.  
  1761.     /* Handle Telnet Debugging Messages */
  1762.     if (deblog || tn_deb || debses) {
  1763.         int i;
  1764.         int deblen=p-str_data-2;
  1765.         char *s=NULL;
  1766.  
  1767.         switch (type) {
  1768.         case 0:
  1769.             s = "AUTH";
  1770.             break;
  1771.         case 1:
  1772.             s = "REJECT";
  1773.             break;
  1774.         case 2:
  1775.             s = "ACCEPT";
  1776.             break;
  1777.         case 3:
  1778.             s = "CHALLENGE";
  1779.             break;
  1780.         case 4:
  1781.             s = "RESPONSE";
  1782.             break;
  1783.         }
  1784.  
  1785.         ckmakxmsg(tn_msg,TN_MSG_LEN,"TELNET SENT SB ",
  1786.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1787.                  str_data[3] == TELQUAL_IS ? "IS" :
  1788.                  (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???")," ",
  1789.                  AUTHTYPE_NAME(authentication_version)," ",
  1790.                  AUTHMODE_NAME(mode)," ",
  1791.                  s," ",NULL);
  1792.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1793.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1794.         debug(F100,tn_msg,"",0);
  1795.         if (tn_deb || debses) tn_debug(tn_msg);
  1796.     }
  1797.  
  1798.     /* Send data */
  1799. #ifdef OS2
  1800.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1801. #endif
  1802.     rc = ttol((CHAR *)str_data, p - str_data);
  1803. #ifdef OS2
  1804.     ReleaseTelnetMutex();
  1805. #endif
  1806.     debug(F111,"SendK4AuthSB","ttol()",rc);
  1807.     return(rc);
  1808. }
  1809.  
  1810. /*  S E N D S R P A U T H S B
  1811.  *  Send a SRP Authentication Subnegotiation to host and
  1812.  *  output appropriate Telnet Debug messages
  1813.  *
  1814.  *  type - Sub Negotiation type
  1815.  *  data - ptr to buffer containing data
  1816.  *  len  - len of buffer if not NUL terminated
  1817.  *
  1818.  *  returns number of characters sent or error value
  1819.  */
  1820.  
  1821. static int
  1822. #ifdef CK_ANSIC
  1823. SendSRPAuthSB(int type, void *data, int len)
  1824. #else
  1825. SendSRPAuthSB(type,data,len) int type; void *data; int len;
  1826. #endif
  1827. {
  1828.     int rc;
  1829.     unsigned char *p = str_data + 3;
  1830.     unsigned char *cd = (unsigned char *)data;
  1831.     extern int sstelnet;
  1832.  
  1833.     /* Check for invalid values */
  1834.     if ( type != SRP_EXP && type != SRP_RESPONSE &&
  1835.          type != SRP_REJECT && type != SRP_ACCEPT &&
  1836.          type != SRP_CHALLENGE && type != SRP_PARAMS &&
  1837.          type != SRP_AUTH)
  1838.         return(0);
  1839.  
  1840.     if (len == -1)                        /* Use strlen() for len */
  1841.         len = strlen((char *)cd);
  1842.  
  1843.     /* Construct Message */
  1844.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1845.     *p++ = AUTHTYPE_SRP;
  1846.     *p = AUTH_CLIENT_TO_SERVER;
  1847.     *p |= auth_how;
  1848. #ifdef CK_ENCRYPTION
  1849.     *p |= auth_crypt;
  1850. #endif
  1851.     p++;
  1852.     *p++ = type;
  1853.     while (len-- > 0) {
  1854.         if ((*p++ = *cd++) == IAC)
  1855.             *p++ = IAC;
  1856.         }
  1857.     *p++ = IAC;
  1858.     *p++ = SE;
  1859.  
  1860.     /* Handle Telnet Debugging Messages */
  1861.     if (deblog || tn_deb || debses) {
  1862.         int i;
  1863.         int deblen=p-str_data-2;
  1864.         char *s=NULL;
  1865.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1866.             auth_crypt;
  1867.  
  1868.         switch (type) {
  1869.         case 0:
  1870.             s = "AUTH";
  1871.             break;
  1872.         case 1:
  1873.             s = "REJECT";
  1874.             break;
  1875.         case 2:
  1876.             s = "ACCEPT";
  1877.             break;
  1878.         case 3:
  1879.             s = "CHALLENGE";
  1880.             break;
  1881.         case 4:
  1882.             s = "RESPONSE";
  1883.             break;
  1884.         case 5:
  1885.             s = "FORWARD";
  1886.             break;
  1887.         case 6:
  1888.             s = "FORWARD_ACCEPT";
  1889.             break;
  1890.         case 7:
  1891.             s = "FORWARD_REJECT";
  1892.             break;
  1893.         case 8:
  1894.             s = "EXP";
  1895.             break;
  1896.         case 9:
  1897.             s = "PARAMS";
  1898.             break;
  1899.         }
  1900.  
  1901.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  1902.                   "TELNET SENT SB ",
  1903.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  1904.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  1905.                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
  1906.                  AUTHTYPE_NAME(authentication_version)," ",
  1907.                  AUTHMODE_NAME(mode)," ",
  1908.                  s," ",NULL);
  1909.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  1910.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  1911.         debug(F100,tn_msg,"",0);
  1912.         if (tn_deb || debses) tn_debug(tn_msg);
  1913.     }
  1914.  
  1915.     /* Send data */
  1916. #ifdef OS2
  1917.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1918. #endif
  1919.     rc = ttol((CHAR *)str_data, p - str_data);
  1920. #ifdef OS2
  1921.     ReleaseTelnetMutex();
  1922. #endif
  1923.     return(rc);
  1924. }
  1925.  
  1926. #ifdef CK_ENCRYPTION
  1927. /*
  1928.  * Function: Enable or disable the encryption process.
  1929.  *
  1930.  * Parameters:
  1931.  *      enable - TRUE to enable, FALSE to disable.
  1932.  */
  1933. static VOID
  1934. #ifdef CK_ANSIC
  1935. auth_encrypt_enable(BOOL enable)
  1936. #else
  1937. auth_encrypt_enable(enable) BOOL enable;
  1938. #endif
  1939. {
  1940.   encrypt_flag = enable;
  1941. }
  1942. #endif
  1943.  
  1944. /*
  1945.  * Function: Abort the authentication process
  1946.  *
  1947.  * Parameters:
  1948.  */
  1949. static VOID
  1950. #ifdef CK_ANSIC
  1951. auth_abort(char *errmsg, long r)
  1952. #else
  1953. auth_abort(errmsg,r) char *errmsg; long r;
  1954. #endif
  1955. {
  1956.     char buf[9];
  1957.     extern int sstelnet;
  1958.  
  1959. #ifdef CK_SSL
  1960.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1961.         return;
  1962.     }
  1963. #endif /* CK_SSL */
  1964.     debug(F111,"auth_abort",errmsg,r);
  1965.  
  1966.     /* Construct Telnet Debugging messages */
  1967.     if (deblog || tn_deb || debses) {
  1968.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  1969.                   "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  1970.                   " IS ",AUTHTYPE_NAME(AUTHTYPE_NULL)," ",
  1971.                    AUTHTYPE_NAME(AUTHTYPE_NULL)," IAC SE",
  1972.                    NULL,NULL,NULL,NULL,NULL
  1973.                  );
  1974.         debug(F100,tn_msg,"",0);
  1975.         if (tn_deb || debses) tn_debug(tn_msg);
  1976.     }
  1977.  
  1978.     /* Construct the Abort message to send to the host   */
  1979.     /* Basicly we change the authentication type to NULL */
  1980.     sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  1981.              sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
  1982.              AUTHTYPE_NULL, IAC, SE);   /* safe */
  1983. #ifdef OS2
  1984.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  1985. #endif
  1986.     ttol((CHAR *)buf, 8);
  1987. #ifdef OS2
  1988.     ReleaseTelnetMutex();
  1989. #endif
  1990.  
  1991.     /* If there is an error message, and error number construct */
  1992.     /* an explanation to display to the user                    */
  1993.     if (errmsg != NULL) {
  1994.         ckstrncpy(strTmp, errmsg, AUTHTMPBL);
  1995.     } else
  1996.         strTmp[0] = '\0';
  1997.  
  1998.  
  1999.     if (r != AUTH_SUCCESS) {
  2000.         ckstrncat(strTmp, "\r\n",AUTHTMPBL);
  2001. #ifdef KRB4
  2002.         if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
  2003.             ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),
  2004.                        AUTHTMPBL);
  2005.             debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
  2006.         }
  2007. #endif
  2008. #ifdef KRB5
  2009.         if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
  2010.             ckstrncat(strTmp, error_message(r),AUTHTMPBL);
  2011.             debug(F111,"auth_abort",error_message(r),r);
  2012.         }
  2013. #endif
  2014.     }
  2015.     printf("Authentication failed: %s\r\n",strTmp);
  2016. #ifdef CKSYSLOG
  2017.     if (ckxsyslog >= SYSLG_LI && ckxlogging) {
  2018.         cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
  2019.                   (char *) szUserNameRequested,
  2020.                   strTmp);
  2021.     }
  2022. #endif /* CKSYSLOG */
  2023.     authentication_version = AUTHTYPE_NULL;
  2024. }
  2025.  
  2026.  
  2027. /*
  2028.  * Function: Copy data to buffer, doubling IAC character if present.
  2029.  *
  2030.  */
  2031. int
  2032. #ifdef CK_ANSIC
  2033. copy_for_net(unsigned char *to, unsigned char *from, int c)
  2034. #else
  2035. copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
  2036. #endif
  2037. {
  2038.     int n;
  2039.  
  2040.     n = c;
  2041.     debug(F111,"copy_for_net","before",n);
  2042.     while (c-- > 0) {
  2043.         if ((*to++ = *from++) == IAC) {
  2044.             n++;
  2045.             *to++ = IAC;
  2046.         }
  2047.     }
  2048.     debug(F111,"copy_for_net","after",n);
  2049.     return n;
  2050. }
  2051.  
  2052. #ifdef CK_SSL
  2053. /*  S E N D S S L A U T H S B
  2054.  *  Send a SSL Authentication Subnegotiation to host and
  2055.  *  output appropriate Telnet Debug messages
  2056.  *
  2057.  *  type - Sub Negotiation type
  2058.  *  data - ptr to buffer containing data
  2059.  *  len  - len of buffer if not NUL terminated
  2060.  *
  2061.  *  returns number of characters sent or error value
  2062.  */
  2063.  
  2064. int
  2065. #ifdef CK_ANSIC
  2066. SendSSLAuthSB(int type, void *data, int len)
  2067. #else
  2068. SendSSLAuthSB(type,data,len) int type; void *data; int len;
  2069. #endif
  2070. {
  2071.     int rc;
  2072.     unsigned char *p = str_data + 3;
  2073.     unsigned char *cd = (unsigned char *)data;
  2074.     extern int sstelnet;
  2075.  
  2076.     /* Check for invalid values */
  2077.     if ( type != SSL_START && type != SSL_ACCEPT &&
  2078.          type != SSL_REJECT)
  2079.         return(0);
  2080.  
  2081.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  2082.         if (ttchk() < 0)
  2083.           return(0);
  2084.         else
  2085.           return(1);
  2086.     }
  2087.  
  2088.     if (len == -1)                        /* Use strlen() for len */
  2089.         len = strlen((char *)cd);
  2090.  
  2091.     /* Construct Message */
  2092.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  2093.     *p++ = AUTHTYPE_SSL;
  2094.     *p = AUTH_CLIENT_TO_SERVER;
  2095.     *p |= auth_how;
  2096. #ifdef CK_ENCRYPTION
  2097.     *p |= auth_crypt;
  2098. #endif
  2099.     p++;
  2100.     *p++ = type;
  2101.     while (len-- > 0) {
  2102.         if ((*p++ = *cd++) == IAC)
  2103.             *p++ = IAC;
  2104.         }
  2105.     *p++ = IAC;
  2106.     *p++ = SE;
  2107.  
  2108.     /* Handle Telnet Debugging Messages */
  2109.     if (deblog || tn_deb || debses) {
  2110.         int i;
  2111.         int deblen=p-str_data-2;
  2112.         char *s=NULL;
  2113.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  2114.             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
  2115.  
  2116.         switch (type) {
  2117.         case SSL_START:
  2118.             s = "START";
  2119.             break;
  2120.         case SSL_ACCEPT:
  2121.             s = "ACCEPT";
  2122.             break;
  2123.         case SSL_REJECT:
  2124.             s = "REJECT";
  2125.             break;
  2126.         }
  2127.  
  2128.         ckmakxmsg(tn_msg,TN_MSG_LEN,
  2129.                   "TELNET SENT SB ",
  2130.                  TELOPT(TELOPT_AUTHENTICATION)," ",
  2131.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  2132.                  str_data[3] == TELQUAL_IS ? "IS" : "???"," ",
  2133.                  AUTHTYPE_NAME(authentication_version)," ",
  2134.                  AUTHMODE_NAME(mode)," ",
  2135.                  s," ",NULL);
  2136.         tn_hex(tn_msg,TN_MSG_LEN,&str_data[7],deblen-7);
  2137.         ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  2138.         debug(F100,tn_msg,"",0);
  2139.         if (tn_deb || debses) tn_debug(tn_msg);
  2140.     }
  2141.  
  2142.     /* Send data */
  2143. #ifdef OS2
  2144.     RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2145. #endif
  2146.     rc = ttol((CHAR *)str_data, p - str_data);
  2147. #ifdef OS2
  2148.     ReleaseTelnetMutex();
  2149. #endif
  2150.     return(rc);
  2151. }
  2152. #endif  /* CK_SSL */
  2153.  
  2154. int
  2155. tn_how_ok(int how)
  2156. {
  2157.     switch ( tn_auth_how ) {
  2158.     case TN_AUTH_HOW_ANY:
  2159.         return(1);
  2160.     case TN_AUTH_HOW_ONE_WAY:
  2161.         return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
  2162.     case TN_AUTH_HOW_MUTUAL:
  2163.         return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
  2164.     default:
  2165.         return(0);
  2166.     }
  2167. }
  2168.  
  2169. int
  2170. tn_enc_ok(int enc)
  2171. {
  2172.     switch ( tn_auth_enc ) {
  2173.     case TN_AUTH_ENC_ANY:
  2174.         if ((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
  2175.             (!ck_ssleay_is_installed
  2176. #ifdef CK_SSL
  2177.              || !ssl_finished_messages ||
  2178.              !(tls_active_flag || ssl_active_flag)
  2179. #endif /* CK_SSL */
  2180.              )) {
  2181. #ifdef CK_SSL
  2182.             if (!ssl_finished_messages)
  2183.                 debug(F100,"tn_enc_ok !ssl_finished_messages","",0);
  2184. #endif /* CK_SSL */
  2185.             return(0);
  2186.         }
  2187.         return(1);
  2188.     case TN_AUTH_ENC_NONE:
  2189.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
  2190.     case TN_AUTH_ENC_TELOPT:
  2191.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
  2192.     case TN_AUTH_ENC_EXCH:
  2193.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
  2194.     case TN_AUTH_ENC_TLS:
  2195.         return(((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) &&
  2196.                ck_ssleay_is_installed()
  2197. #ifdef CK_SSL
  2198.                && ssl_finished_messages &&
  2199.                (tls_active_flag || ssl_active_flag)
  2200. #endif /* CK_SSL */
  2201.            );
  2202.     default:
  2203.         return(0);
  2204.     }
  2205. }
  2206.  
  2207. static int
  2208. atok(int at) {
  2209.     int i;
  2210.     if ( auth_type_user[0] == AUTHTYPE_AUTO )
  2211.         return(1);
  2212.     if ( auth_type_user[0] == AUTHTYPE_NULL )
  2213.         return(0);
  2214.  
  2215.     for ( i=0;
  2216.           i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
  2217.           i++ ) {
  2218.         if ( auth_type_user[i] == at )
  2219.             return(1);
  2220.     }
  2221.  
  2222.     return(0);
  2223. }
  2224.  
  2225.  
  2226. /*
  2227.  * Function: Parse authentication send command
  2228.  *
  2229.  * Parameters:
  2230.  *  parsedat - the sub-command data.
  2231.  *
  2232.  *      end_sub - index of the character in the 'parsedat' array which
  2233.  *              is the last byte in a sub-negotiation
  2234.  *
  2235.  * Returns: Kerberos error code.
  2236.  */
  2237.  
  2238. static unsigned char send_list[512];
  2239. static int  send_len = 0;
  2240.  
  2241. _PROTOTYP(static int auth_send, (unsigned char *parsedat, int end_sub));
  2242.  
  2243. static int
  2244. #ifdef CK_ANSIC
  2245. auth_resend(int type)
  2246. #else
  2247. auth_resend(type) int type;
  2248. #endif /* CK_ANSIC */
  2249. {
  2250.     int i=2;
  2251.     while (i+1 <= send_len) {
  2252.         if (send_list[i] == type) {
  2253.             int j;
  2254.             send_len -= 2;
  2255.             for (j = i; j < send_len; j++)
  2256.                 send_list[j] = send_list[j+2];
  2257.         } else {
  2258.             i += 2;
  2259.         }
  2260.     }
  2261.     return(auth_send(send_list,send_len));
  2262. }
  2263.  
  2264. static int
  2265. #ifdef CK_ANSIC
  2266. auth_send(unsigned char *parsedat, int end_sub)
  2267. #else
  2268. auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  2269. #endif
  2270. {
  2271.     static unsigned char buf[4096];
  2272.     unsigned char *pname;
  2273.     int plen;
  2274.     int r;
  2275.     int i;
  2276.     int mode;
  2277. #ifdef MIT_CURRENT
  2278. #ifdef CK_ENCRYPTION
  2279.     krb5_data data;
  2280.     krb5_enc_data encdata;
  2281.     krb5_error_code code;
  2282.     krb5_keyblock random_key;
  2283. #endif /* ENCRYPTION */
  2284. #endif /* MIT_CURRENT */
  2285. #ifdef KRB5
  2286.     int krb5_msg = 0;
  2287. #endif /* KRB5 */
  2288. #ifdef KRB4
  2289.     int krb4_msg = 0;
  2290. #endif /* KRB4 */
  2291. #ifdef GSSAPI_KRB5
  2292.     int gssk5_msg = 0;
  2293. #endif /* GSSAPI_KRB5 */
  2294.     int iaccnt=0;
  2295.  
  2296. #ifdef CK_SSL
  2297.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  2298.         return(AUTH_SUCCESS);
  2299. #endif /* CK_SSL */
  2300.  
  2301.     auth_how = -1;              /* We have not found an auth method  */
  2302.     auth_crypt = 0;             /* We are not using encryption (yet) */
  2303.     send_len = end_sub > 512 ? 512 : end_sub;
  2304.     memcpy(send_list,parsedat,send_len);
  2305.  
  2306.     /* Search the list of acceptable Authentication types sent from */
  2307.     /* the host and find one that we support                        */
  2308.  
  2309.     /* For Kerberos authentications, try to determine if we have a  */
  2310.     /* valid TGT, if not skip over the authentication type because  */
  2311.     /* we wouldn't be able to successfully login anyway.  Perhaps   */
  2312.     /* there is another supported authentication which we could use */
  2313.  
  2314. #ifdef NO_FTP_AUTH
  2315.     /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
  2316.     /* for Kerberos or SRP.                                         */
  2317. #endif /* NO_FTP_AUTH */
  2318.  
  2319.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  2320.     for (i = 2; i+1 <= end_sub; i += 2) {
  2321. #ifdef NTLM
  2322.         if (parsedat[i] == AUTHTYPE_NTLM &&
  2323.              ck_ntlm_is_valid(1) &&
  2324.              ntlm_auth_send() == 0) {
  2325.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2326.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2327. #ifdef CK_ENCRYPTION
  2328.                 /* NTLM does not support Telnet Encryption */
  2329.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2330.                     continue;
  2331.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2332. #endif /* CK_ENCRYPTION */
  2333.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2334.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2335.                 authentication_version = AUTHTYPE_NTLM;
  2336.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2337.                 break;
  2338.             }
  2339.         }
  2340. #endif /* NTLM */
  2341. #ifdef CK_SSL
  2342.         if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
  2343. #ifdef SSLDLL
  2344.              ck_ssleay_is_installed() &&
  2345. #endif /* SSLDLL */
  2346.              !tls_active_flag && !ssl_active_flag
  2347. #ifndef USE_CERT_CB
  2348.              && tls_load_certs(ssl_ctx,ssl_con,0)
  2349. #endif /* USE_CERT_CB */
  2350.              ) {
  2351.  
  2352.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2353.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2354. #ifdef CK_ENCRYPTION
  2355.                 /* SSL does not support Telnet Encryption */
  2356.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2357.                     continue;
  2358.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2359. #endif /* CK_ENCRYPTION */
  2360.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2361.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2362.                 authentication_version = AUTHTYPE_SSL;
  2363.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2364.                 break;
  2365.             }
  2366.         }
  2367. #endif /* SSL */
  2368. #ifdef CK_SRP
  2369.         if ( parsedat[i] == AUTHTYPE_SRP
  2370. #ifdef SRPDLL
  2371.              && hSRP
  2372. #endif /* SRPDLL */
  2373. #ifdef NO_FTP_AUTH
  2374.              && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2375. #endif /* NO_FTP_AUTH */
  2376.              ) {
  2377.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2378.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2379. #ifdef PRE_SRP_1_4_5
  2380.                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2381.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2382.                     continue;
  2383. #endif /* PRE_SRP_1_4_5 */
  2384.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2385.                      AUTH_ENCRYPT_USING_TELOPT) &&
  2386.                     (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2387.                      TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2388.                     continue;
  2389.  
  2390.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2391. #ifdef CK_ENCRYPTION
  2392.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2393.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2394.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2395.                 }
  2396. #endif /* CK_ENCRYPTION */
  2397. #ifdef CK_SSL
  2398.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2399.                      ck_ssleay_is_installed() &&
  2400.                      (tls_active_flag || ssl_active_flag) ) {
  2401.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2402.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2403.                 }
  2404. #endif /* CK_SSL */
  2405.                 authentication_version = AUTHTYPE_SRP;
  2406.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2407.                 break;
  2408.             }
  2409.         }
  2410. #endif /* SRP */
  2411. #ifdef GSSAPI_KRB5
  2412.         if (parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
  2413.             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2414.             AUTH_ENCRYPT_AFTER_EXCHANGE &&
  2415. #ifdef OS2
  2416.             hGSSAPI &&
  2417. #endif /* OS2 */
  2418. #ifdef NO_FTP_AUTH
  2419.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2420. #endif /* NO_FTP_AUTH */
  2421.              ck_gssapi_is_installed() && !gssk5_msg)
  2422.         {
  2423.             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2424.                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2425.                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
  2426.             {
  2427.                 /* If we are auto-getting TGTs, try */
  2428.                 if ( !ck_krb5_is_tgt_valid() ) {
  2429.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2430.                 }
  2431.                 gssk5_msg = 1;
  2432.             }
  2433.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2434.                       AUTH_CLIENT_TO_SERVER &&
  2435.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2436.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2437. #ifdef CK_ENCRYPTION
  2438.                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
  2439.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2440.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2441.                 }
  2442. #endif /* CK_ENCRYPTION */
  2443.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2444.                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
  2445.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2446.                 break;
  2447.             }
  2448.         }
  2449. #endif /* GSSAPI_KRB5 */
  2450. #ifdef KRB5
  2451.         if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2452. #ifdef OS2
  2453.              hKRB5_32 &&
  2454. #endif /* OS2 */
  2455. #ifdef NO_FTP_AUTH
  2456.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2457. #endif /* NO_FTP_AUTH */
  2458.              ck_krb5_is_installed() && !krb5_msg) {
  2459.  
  2460.             /* Without encryption we can't perform mutual authentication */
  2461.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2462.                  !ck_crypt_is_installed())
  2463.                 continue;
  2464.  
  2465.             /* Skip over entries that request credential forwarding */
  2466.             /* if we are not forwarding.                            */
  2467.             if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2468.                 (forward_flag &&
  2469.                   ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2470.                 continue;
  2471.  
  2472.             if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2473.                                 parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2474.                                 parsedat[i+1] & INI_CRED_FWD_MASK) )
  2475.             {
  2476.                 /* If we are auto-getting TGTs, try */
  2477.                 if ( !ck_krb5_is_tgt_valid() ) {
  2478.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2479.                 }
  2480.                 krb5_msg = 1;
  2481.             }
  2482.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2483.                       AUTH_CLIENT_TO_SERVER &&
  2484.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2485.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2486.                      AUTH_ENCRYPT_USING_TELOPT) &&
  2487.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2488.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2489.                     continue;
  2490.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2491.                      AUTH_ENCRYPT_START_TLS) &&
  2492.                      (!ck_ssleay_is_installed()
  2493. #ifdef CK_SSL
  2494.                        || !(tls_active_flag || ssl_active_flag)
  2495. #endif /* CK_SSL */
  2496.                        ))
  2497.                     continue;
  2498.  
  2499.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2500. #ifdef CK_ENCRYPTION
  2501.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2502.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2503.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2504.                 }
  2505. #endif /* CK_ENCRYPTION */
  2506. #ifdef CK_SSL
  2507.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2508.                      ck_ssleay_is_installed() &&
  2509.                      (tls_active_flag || ssl_active_flag) ) {
  2510.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2511.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2512.                 }
  2513. #endif /* CK_SSL */
  2514.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2515.                 authentication_version = AUTHTYPE_KERBEROS_V5;
  2516.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2517.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2518.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2519.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2520.                 }
  2521.                 break;
  2522.             }
  2523.         }
  2524. #endif /* KRB5 */
  2525. #ifdef KRB4
  2526.         if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2527. #ifdef OS2
  2528.              hKRB4_32 &&
  2529. #endif /* OS2 */
  2530. #ifdef NO_FTP_AUTH
  2531.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2532. #endif /* NO_FTP_AUTH */
  2533.              ck_krb4_is_installed() && !krb4_msg) {
  2534.             int rc = 0;
  2535.  
  2536.             /* Without encryption we can't perform mutual authentication */
  2537.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2538.                  !ck_crypt_is_installed() )
  2539.                 continue;
  2540.  
  2541.             if ( !k4_auth_send() )
  2542.             {
  2543.                 /* If we are auto-getting TGTs, try */
  2544.                 if ( !ck_krb4_is_tgt_valid() ) {
  2545.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2546.                 }
  2547.                 krb4_msg = 1;
  2548.             }
  2549.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2550.                       AUTH_CLIENT_TO_SERVER &&
  2551.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2552. #ifdef CK_ENCRYPTION
  2553.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2554.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2555.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2556.                     continue;
  2557.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2558.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2559.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2560.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2561.                 }
  2562. #endif /* CK_ENCRYPTION */
  2563.                 authentication_version = AUTHTYPE_KERBEROS_V4;
  2564.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2565.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2566.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2567.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2568.                 }
  2569.                 break;
  2570.             }
  2571.         }
  2572. #endif /* KRB4 */
  2573.     }
  2574.     } else {
  2575.         for (i = 2; i+1 <= end_sub; i += 2) {
  2576. #ifdef CK_SSL
  2577.             if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
  2578. #ifdef SSLDLL
  2579.                  ck_ssleay_is_installed() &&
  2580. #endif /* SSLDLL */
  2581.                  !tls_active_flag && !ssl_active_flag && ssl_initialized
  2582. #ifndef USE_CERT_CB
  2583.                  && tls_load_certs(ssl_ctx,ssl_con,0)
  2584. #endif /* USE_CERT_CB */
  2585.                  )
  2586.             {
  2587.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2588.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2589. #ifdef CK_ENCRYPTION
  2590.                     /* SSL does not support Telnet Encryption */
  2591.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2592.                         continue;
  2593.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2594. #endif /* CK_ENCRYPTION */
  2595.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2596.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2597.                     authentication_version = AUTHTYPE_SSL;
  2598.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2599.                     break;
  2600.                 }
  2601.             }
  2602. #endif /* SSL */
  2603. #ifdef CK_SRP
  2604.             if ( atok(AUTHTYPE_SRP) &&
  2605.                  parsedat[i] == AUTHTYPE_SRP
  2606. #ifdef SRPDLL
  2607.                  && hSRP
  2608. #endif /* SRPDLL */
  2609. #ifdef NO_FTP_AUTH
  2610.                  && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2611. #endif /* NO_FTP_AUTH */
  2612.                  ) {
  2613.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2614.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2615. #ifdef PRE_SRP_1_4_5
  2616.                 if (parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2617.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2618.                     continue;
  2619. #endif /* PRE_SRP_1_4_5 */
  2620.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2621.                      AUTH_ENCRYPT_USING_TELOPT) &&
  2622.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2623.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2624.                     continue;
  2625.                 if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2626.                      AUTH_ENCRYPT_START_TLS) &&
  2627.                      (!ck_ssleay_is_installed()
  2628. #ifdef CK_SSL
  2629.                        || !(tls_active_flag || ssl_active_flag)
  2630. #endif /* CK_SSL */
  2631.                        ))
  2632.                     continue;
  2633.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2634. #ifdef CK_ENCRYPTION
  2635.                     if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2636.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2637.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2638.                     }
  2639. #endif /* CK_ENCRYPTION */
  2640. #ifdef CK_SSL
  2641.                 if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2642.                      ck_ssleay_is_installed() &&
  2643.                      (tls_active_flag || ssl_active_flag) ) {
  2644.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2645.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2646.                 }
  2647. #endif /* CK_SSL */
  2648.                     authentication_version = AUTHTYPE_SRP;
  2649.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2650.                     break;
  2651.                 }
  2652.             }
  2653. #endif /* SRP */
  2654. #ifdef GSSAPI_KRB5
  2655.         if (atok(AUTHTYPE_GSSAPI_KRB5) &&
  2656.             parsedat[i] == AUTHTYPE_GSSAPI_KRB5 &&
  2657.             (parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2658.             AUTH_ENCRYPT_AFTER_EXCHANGE &&
  2659. #ifdef OS2
  2660.             hGSSAPI &&
  2661. #endif /* OS2 */
  2662. #ifdef NO_FTP_AUTH
  2663.             strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2664. #endif /* NO_FTP_AUTH */
  2665.             ck_gssapi_is_installed() && !gssk5_msg)
  2666.         {
  2667.             if ( !gssk5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2668.                                   parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2669.                                   parsedat[i+1] & INI_CRED_FWD_MASK) )
  2670.             {
  2671.                 /* If we are auto-getting TGTs, try */
  2672.                 if ( !ck_krb5_is_tgt_valid() ) {
  2673.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2674.                 }
  2675.                 gssk5_msg = 1;
  2676.             }
  2677.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2678.                       AUTH_CLIENT_TO_SERVER &&
  2679.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2680.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2681. #ifdef CK_ENCRYPTION
  2682.                 if ( auth_crypt == AUTH_ENCRYPT_AFTER_EXCHANGE ) {
  2683.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2684.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2685.                 }
  2686. #endif /* CK_ENCRYPTION */
  2687.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2688.                 authentication_version = AUTHTYPE_GSSAPI_KRB5;
  2689.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2690.                 break;
  2691.             }
  2692.         }
  2693. #endif /* GSSAPI_KRB5 */
  2694. #ifdef KRB5
  2695.             if ( atok(AUTHTYPE_KERBEROS_V5) &&
  2696.                  parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2697. #ifdef OS2
  2698.                  hKRB5_32 &&
  2699. #endif /* OS2 */
  2700. #ifdef NO_FTP_AUTH
  2701.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2702. #endif /* NO_FTP_AUTH */
  2703.                  ck_krb5_is_installed() && !krb5_msg) {
  2704.  
  2705.                 /* Without encryption we can't perform mutual authentication */
  2706.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2707.                      !ck_crypt_is_installed())
  2708.                     continue;
  2709.  
  2710.                 /* Skip over entries that request credential forwarding */
  2711.                 /* if we are not forwarding.                            */
  2712.                 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2713.                      (forward_flag &&
  2714.                        ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2715.                     continue;
  2716.  
  2717.                 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2718.                                     parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2719.                                     parsedat[i+1] & INI_CRED_FWD_MASK) )
  2720.                 {
  2721.                     /* If we are auto-getting TGTs, try */
  2722.                     if ( !ck_krb5_is_tgt_valid() ) {
  2723.                         printf(
  2724.                            "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2725.                     }
  2726.                     krb5_msg = 1;
  2727.                 }
  2728.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2729.                           AUTH_CLIENT_TO_SERVER &&
  2730.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2731.                 {
  2732.                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2733.                          AUTH_ENCRYPT_USING_TELOPT) &&
  2734.                          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2735.                            TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2736.                         continue;
  2737.                     if (((parsedat[i+1] & AUTH_ENCRYPT_MASK) ==
  2738.                          AUTH_ENCRYPT_START_TLS) &&
  2739.                          (!ck_ssleay_is_installed()
  2740. #ifdef CK_SSL
  2741.                            || !(tls_active_flag || ssl_active_flag)
  2742. #endif /* CK_SSL */
  2743.                            ))
  2744.                         continue;
  2745.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2746. #ifdef CK_ENCRYPTION
  2747.                     if (auth_crypt) {
  2748.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2749.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2750.                     }
  2751. #endif /* CK_ENCRYPTION */
  2752. #ifdef CK_SSL
  2753.                     if ( auth_crypt == AUTH_ENCRYPT_START_TLS &&
  2754.                          ck_ssleay_is_installed() &&
  2755.                          (tls_active_flag || ssl_active_flag) ) {
  2756.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2757.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2758.                     }
  2759. #endif /* CK_SSL */
  2760.                     authentication_version = AUTHTYPE_KERBEROS_V5;
  2761.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2762.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2763.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2764.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2765.                     }
  2766.                     break;
  2767.                 }
  2768.             }
  2769. #endif /* KRB5 */
  2770. #ifdef KRB4
  2771.             if ( atok(AUTHTYPE_KERBEROS_V4) &&
  2772.                  parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2773. #ifdef OS2
  2774.                  hKRB4_32 &&
  2775. #endif /* OS2 */
  2776. #ifdef NO_FTP_AUTH
  2777.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2778. #endif /* NO_FTP_AUTH */
  2779.                  ck_krb4_is_installed() && !krb4_msg) {
  2780.                 int rc = 0;
  2781.  
  2782.                 /* Without encryption we can't perform mutual authentication */
  2783.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2784.                      !ck_crypt_is_installed())
  2785.                     continue;
  2786.  
  2787.                 if ( !k4_auth_send() )
  2788.                 {
  2789.                     /* If we are auto-getting TGTs, try */
  2790.                     if ( !ck_krb4_is_tgt_valid() ) {
  2791.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2792.                     }
  2793.                     krb4_msg = 1;
  2794.                 }
  2795.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2796.                           AUTH_CLIENT_TO_SERVER &&
  2797.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2798.                 {
  2799. #ifdef CK_ENCRYPTION
  2800.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2801.                         (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2802.                          TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2803.                       continue;
  2804.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2805.                     if (auth_crypt) {
  2806.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2807.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2808.                     }
  2809. #endif /* CK_ENCRYPTION */
  2810.                     authentication_version = AUTHTYPE_KERBEROS_V4;
  2811.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2812.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2813.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2814.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2815.                     }
  2816.                     break;
  2817.                 }
  2818.             }
  2819. #endif /* KRB4 */
  2820. #ifdef NTLM
  2821.         if ( atok(AUTHTYPE_NTLM) &&
  2822.              parsedat[i] == AUTHTYPE_NTLM &&
  2823.              ck_ntlm_is_valid(1) &&
  2824.              ntlm_auth_send() == 0) {
  2825.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2826.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2827. #ifdef CK_ENCRYPTION
  2828.                 /* NTLM does not support Telnet Encryption */
  2829.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2830.                     continue;
  2831.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2832. #endif /* CK_ENCRYPTION */
  2833.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2834.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2835.                 authentication_version = AUTHTYPE_NTLM;
  2836.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2837.                 break;
  2838.             }
  2839.         }
  2840. #endif /* NTLM */
  2841.         }
  2842.     }
  2843.  
  2844.     if (auth_how == -1) {               /* Did we find one? */
  2845.         switch ( auth_type_user[0] ) {  /* If not, abort the negotiation */
  2846.         case AUTHTYPE_NULL:
  2847.             auth_abort("User refused to accept any authentication method",0);
  2848.             break;
  2849.         case AUTHTYPE_AUTO:
  2850.             auth_abort("No authentication method available", 0);
  2851.             break;
  2852.         default: {
  2853.             char msg[80];
  2854.             ckmakmsg(msg,80,AUTHTYPE_NAME(auth_type_user[0]),
  2855.                       " could not be negotiated",NULL,NULL
  2856.                      );
  2857.             auth_abort(msg, 0);
  2858.         }
  2859.         }
  2860.         auth_finished(AUTH_REJECT);
  2861.         return AUTH_FAILURE;
  2862.     }
  2863.  
  2864.     printf("Authenticating with %s\r\n",
  2865.             AUTHTYPE_NAME(authentication_version));
  2866.  
  2867.     /* Send Telnet Auth Name message (if necessary) */
  2868.     switch ( authentication_version ) {
  2869.     case AUTHTYPE_SRP:
  2870.     case AUTHTYPE_KERBEROS_V4:
  2871.     case AUTHTYPE_KERBEROS_V5:
  2872.     case AUTHTYPE_GSSAPI_KRB5:
  2873.         /* if we do not have a name to login with get one now. */
  2874.         while ( szUserName[0] == '\0' ) {
  2875.             extern char * tn_pr_uid;
  2876.             readtext(tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
  2877.                       szUserName,63);
  2878.         }
  2879.         plen = strlen(szUserName);
  2880.         pname = (unsigned char *) szUserName;
  2881.  
  2882.         /* Construct Telnet Debugging Message */
  2883.         if (deblog || tn_deb || debses) {
  2884.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  2885.                        "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2886.                        " NAME ",pname," IAC SE",NULL,
  2887.                        NULL,NULL,NULL,NULL,NULL,NULL
  2888.                      );
  2889.             debug(F100,tn_msg,"",0);
  2890.             if (tn_deb || debses) tn_debug(tn_msg);
  2891.         }
  2892.  
  2893.         /* Construct and send Authentication Name subnegotiation */
  2894.         if ( plen < sizeof(buf) - 6 ) {
  2895.             sprintf(buf, "%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  2896.                      TELQUAL_NAME);
  2897.             memcpy(&buf[4], pname, plen);               /* safe */
  2898.             sprintf(&buf[plen + 4], "%c%c", IAC, SE);   /* safe */
  2899. #ifdef OS2
  2900.             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2901. #endif
  2902.             ttol((CHAR *)buf, plen+6);
  2903. #ifdef OS2
  2904.             ReleaseTelnetMutex();
  2905. #endif
  2906.         } else {
  2907.             sprintf(buf, "%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  2908.                      TELQUAL_NAME, IAC, SE);    /* safe */
  2909. #ifdef OS2
  2910.             RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2911. #endif
  2912.             ttol((CHAR *)buf, 6);
  2913. #ifdef OS2
  2914.             ReleaseTelnetMutex();
  2915. #endif
  2916.         }
  2917.     }
  2918.  
  2919.     /* Construct Authentication Mode subnegotiation message (if necessary) */
  2920.     switch ( authentication_version ) {
  2921.     case AUTHTYPE_SRP:
  2922.     case AUTHTYPE_KERBEROS_V4:
  2923.     case AUTHTYPE_KERBEROS_V5:
  2924.     case AUTHTYPE_GSSAPI_KRB5:
  2925.     case AUTHTYPE_NTLM:
  2926.         mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) | auth_crypt
  2927. #ifdef USE_INI_CRED_FWD
  2928.                | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
  2929.                   auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  2930. #endif /* USE_INI_CRED_FWD */
  2931.                ;
  2932.         sprintf(buf, "%c%c%c%c%c%c%c",
  2933.                  IAC, SB, TELOPT_AUTHENTICATION,
  2934.                  TELQUAL_IS,
  2935.                  authentication_version,
  2936.                  mode,
  2937.                  KRB_AUTH);     /* safe */
  2938.         break;
  2939.     }
  2940.  
  2941.     /* Send initial authentication data */
  2942.     switch ( authentication_version ) {
  2943. #ifdef CK_SSL
  2944.     case AUTHTYPE_SSL:
  2945.         SendSSLAuthSB(SSL_START,NULL,0);
  2946.         break;
  2947. #endif /* SSL */
  2948. #ifdef CK_SRP
  2949.     case AUTHTYPE_SRP:
  2950.         sprintf(&buf[7], "%c%c", IAC, SE);      /* safe */
  2951.         if (deblog || tn_deb || debses) {
  2952.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  2953.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2954.                       " IS ",AUTHTYPE_NAME(authentication_version),
  2955.                       " AUTH ",AUTHMODE_NAME(mode)," IAC SE",
  2956.                       NULL,NULL,NULL,NULL,NULL
  2957.                      );
  2958.             debug(F100,tn_msg,"",0);
  2959.             if (tn_deb || debses) tn_debug(tn_msg);
  2960.         }
  2961. #ifdef OS2
  2962.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  2963. #endif
  2964.         ttol((CHAR *)buf, 9);
  2965. #ifdef OS2
  2966.         ReleaseTelnetMutex();
  2967. #endif
  2968.         break;
  2969. #endif /* SRP */
  2970. #ifdef NTLM
  2971.     case AUTHTYPE_NTLM: {
  2972.         int length = 0;
  2973.  
  2974.         for ( i=0 ; i<NTLMSecBuf[0].cbBuffer ; i++ ) {
  2975.             if ( ((char *)NTLMSecBuf[0].pvBuffer)[i] == IAC )
  2976.                 iaccnt++;
  2977.         }
  2978.  
  2979.         if ( ( 2*sizeof(ULONG) + NTLMSecBuf[0].cbBuffer + iaccnt + 10)  <
  2980.              sizeof(buf) ) {
  2981.             length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],
  2982.                                    2*sizeof(ULONG));
  2983.             length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
  2984.                                   NTLMSecBuf[0].cbBuffer);
  2985.         }
  2986.         sprintf(&buf[7+length], "%c%c", IAC, SE);
  2987.  
  2988.         if (deblog || tn_deb || debses) {
  2989.             int i;
  2990.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  2991.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION),
  2992.                       " IS ",AUTHTYPE_NAME(authentication_version)," ",
  2993.                       AUTHMODE_NAME(mode)," NTLM_AUTH ",
  2994.                        NULL,NULL,NULL,NULL,NULL
  2995.                       );
  2996.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],length);
  2997.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  2998.             debug(F100,tn_msg,"",0);
  2999.             if (tn_deb || debses) tn_debug(tn_msg);
  3000.         }
  3001. #ifdef OS2
  3002.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3003. #endif
  3004.         ttol((CHAR *)buf, length+9);
  3005. #ifdef OS2
  3006.         ReleaseTelnetMutex();
  3007. #endif
  3008.         break;
  3009.     }
  3010. #endif /* NTLM */
  3011. #ifdef KRB4
  3012.     case AUTHTYPE_KERBEROS_V4:
  3013.         for ( i=0 ; i<k4_auth.length ; i++ ) {
  3014.             if ( k4_auth.dat[i] == IAC )
  3015.                 iaccnt++;
  3016.         }
  3017.  
  3018.         if ( k4_auth.length + iaccnt + 10 < sizeof(buf) )
  3019.           k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
  3020.         else
  3021.             k4_auth.length = 0;
  3022.         sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
  3023.  
  3024.         if (deblog || tn_deb || debses) {
  3025.             int i;
  3026.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3027.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3028.                       AUTHTYPE_NAME(authentication_version)," ",
  3029.                       AUTHMODE_NAME(mode)," AUTH ",
  3030.                       NULL,NULL,NULL,NULL,NULL
  3031.                      );
  3032.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],k4_auth.length);
  3033.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3034.             debug(F100,tn_msg,"",0);
  3035.             if (tn_deb || debses) tn_debug(tn_msg);
  3036.         }
  3037. #ifdef OS2
  3038.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3039. #endif
  3040.         ttol((CHAR *)buf, k4_auth.length+9);
  3041. #ifdef OS2
  3042.         ReleaseTelnetMutex();
  3043. #endif
  3044.  
  3045. #ifndef REMOVE_FOR_EXPORT
  3046. #ifdef CK_ENCRYPTION
  3047.         /*
  3048.          * If we are doing mutual authentication, get set up to send
  3049.          * the challenge, and verify it when the response comes back.
  3050.          */
  3051.         if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  3052.             register int i;
  3053.             int rc = 0;
  3054.  
  3055. #ifdef MIT_CURRENT
  3056.             data.data = cred.session;
  3057.             data.length = 8; /* sizeof(cred.session) */;
  3058.  
  3059.             if (code = krb5_c_random_seed(k5_context, &data)) {
  3060.                 com_err("libtelnet", code,
  3061.                          "while seeding random number generator");
  3062.                 return(0);
  3063.             }
  3064.  
  3065.             if (code = krb5_c_make_random_key(k5_context,
  3066.                                                ENCTYPE_DES_CBC_RAW,
  3067.                                                &random_key)) {
  3068.                 com_err("libtelnet", code,
  3069.                          "while creating random session key");
  3070.                 return(0);
  3071.             }
  3072.  
  3073.             /* the krb4 code uses ecb mode, but on a single block
  3074.             with a zero ivec, ecb and cbc are the same */
  3075.             k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  3076.             k4_krbkey.length = 8;
  3077.             k4_krbkey.contents = cred.session;
  3078.  
  3079.             encdata.ciphertext.data = random_key.contents;
  3080.             encdata.ciphertext.length = random_key.length;
  3081.             encdata.enctype = ENCTYPE_UNKNOWN;
  3082.  
  3083.             data.data = k4_session_key;
  3084.             data.length = 8;
  3085.  
  3086.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3087.                                    &encdata, &data);
  3088.  
  3089.             krb5_free_keyblock_contents(k5_context, &random_key);
  3090.  
  3091.             if (code) {
  3092.                 com_err("libtelnet", code, "while encrypting random key");
  3093.                 return(0);
  3094.             }
  3095.  
  3096.             encdata.ciphertext.data = k4_session_key;
  3097.             encdata.ciphertext.length = 8;
  3098.             encdata.enctype = ENCTYPE_UNKNOWN;
  3099.  
  3100.             data.data = k4_challenge;
  3101.             data.length = 8;
  3102.  
  3103.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3104.                                    &encdata, &data);
  3105. #else /* MIT_CURRENT */
  3106.             memset(k4_sched,0,sizeof(Schedule));
  3107.             hexdump("auth_send",cred.session,8);
  3108.             rc = des_key_sched(cred.session, k4_sched);
  3109.             if ( rc == -1 ) {
  3110.                 printf("?Invalid DES key specified in credentials\r\n");
  3111.                 debug(F110,"auth_send",
  3112.                       "invalid DES Key specified in credentials",0);
  3113.             } else if ( rc == -2 ) {
  3114.                 printf("?Weak DES key specified in credentials\r\n");
  3115.                 debug(F110,"auth_send",
  3116.                       "weak DES Key specified in credentials",0);
  3117.             } else if ( rc != 0 ) {
  3118.                 printf("?DES Key Schedule not set by credentials\r\n");
  3119.                 debug(F110,"auth_send",
  3120.                       "DES Key Schedule not set by credentials",0);
  3121.             }
  3122.             hexdump("auth_send schedule",k4_sched,8*16);
  3123.  
  3124.             des_set_random_generator_seed(cred.session);
  3125.  
  3126.             do {
  3127.                 des_new_random_key(k4_session_key);
  3128.                 des_fixup_key_parity(k4_session_key);
  3129.             } while ( ck_des_is_weak_key(k4_session_key) );
  3130.  
  3131.             hexdump("auth_send des_new_random_key(k4_session_key)",
  3132.                      k4_session_key,8);
  3133.  
  3134.             /* Decrypt the session key so that we can send it to the */
  3135.             /* host as a challenge                                   */
  3136. #ifdef NT
  3137.             des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
  3138. #else /* NT */
  3139.             des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
  3140. #endif /* NT */
  3141.             hexdump(
  3142.                 "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
  3143.                 k4_session_key,8
  3144.                     );
  3145.             /* Prepare the result of the challenge */
  3146.             /* Decrypt the session_key, add 1, and then encrypt it */
  3147.             /* The result stored in k4_challenge should match the  */
  3148.             /* KRB4_RESPONSE value from the host.                  */
  3149. #ifdef NT
  3150.             des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
  3151. #else /* NT */
  3152.             des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
  3153. #endif /* NT */
  3154.  
  3155.             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
  3156.                      k4_challenge,8);
  3157. #endif /* MIT_CURRENT */
  3158.             /*
  3159.             * Increment the challenge by 1, and encrypt it for
  3160.             * later comparison.
  3161.             */
  3162.             for (i = 7; i >= 0; --i) {
  3163.                 register int x;
  3164.                 x = (unsigned int)k4_challenge[i] + 1;
  3165.                 k4_challenge[i] = x;    /* ignore overflow */
  3166.                 if (x < 256)            /* if no overflow, all done */
  3167.                     break;
  3168.             }
  3169.             hexdump("auth_send k4_challenge+1",k4_challenge,8);
  3170. #ifdef MIT_CURRENT
  3171.             data.data = k4_challenge;
  3172.             data.length = 8;
  3173.  
  3174.             encdata.ciphertext.data = k4_challenge;
  3175.             encdata.ciphertext.length = 8;
  3176.             encdata.enctype = ENCTYPE_UNKNOWN;
  3177.  
  3178.             if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
  3179.                                        &encdata)) {
  3180.                 com_err("libtelnet", code, "while encrypting random key");
  3181.                 return(0);
  3182.             }
  3183. #else /* MIT_CURRENT */
  3184. #ifdef NT
  3185.             des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  3186. #else /* NT */
  3187.             des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  3188. #endif /* NT */
  3189.             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
  3190.                      k4_challenge,8);
  3191. #endif /* MIT_CURRENT */
  3192.         }
  3193. #endif  /* ENCRYPTION */
  3194. #endif /* REMOVE_FOR_EXPORT */
  3195.         break;
  3196. #endif /* KRB4 */
  3197. #ifdef GSSAPI_KRB5
  3198.     case AUTHTYPE_GSSAPI_KRB5:
  3199.         for ( i=0 ; i<gss_send_tok.length ; i++ ) {
  3200.             if ( ((char *)gss_send_tok.value)[i] == IAC )
  3201.                 iaccnt++;
  3202.         }
  3203.  
  3204.         if ( gss_send_tok.length + iaccnt + 10 < sizeof(buf) )
  3205.             gss_send_tok.length = copy_for_net(&buf[7], gss_send_tok.value,
  3206.                                                gss_send_tok.length);
  3207.         else
  3208.             gss_send_tok.length = 0;
  3209.         sprintf(&buf[gss_send_tok.length+7], "%c%c", IAC, SE);       /* safe */
  3210.         if (deblog || tn_deb || debses) {
  3211.             int i;
  3212.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3213.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3214.                       AUTHTYPE_NAME(authentication_version)," ",
  3215.                       AUTHMODE_NAME(mode)," AUTH ",
  3216.                       NULL,NULL,NULL,NULL,NULL
  3217.                      );
  3218.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],gss_send_tok.length);
  3219.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3220.             debug(F100,tn_msg,"",0);
  3221.             if (tn_deb || debses) tn_debug(tn_msg);
  3222.         }
  3223. #ifdef OS2
  3224.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3225. #endif
  3226.         ttol((CHAR *)buf, gss_send_tok.length+9);
  3227. #ifdef OS2
  3228.         ReleaseTelnetMutex();
  3229. #endif
  3230.         break;
  3231. #endif /* GSSAPI_KRB5 */
  3232. #ifdef KRB5
  3233.     case AUTHTYPE_KERBEROS_V5:
  3234.         debug(F111,"auth_send KRB5","k5_auth.length",k5_auth.length);
  3235.         for ( i=0 ; i<k5_auth.length ; i++ ) {
  3236.             if ( ((char *)k5_auth.data)[i] == IAC )
  3237.                 iaccnt++;
  3238.         }
  3239.  
  3240.         if ( k5_auth.length + iaccnt + 10 < sizeof(buf) )
  3241.           k5_auth.length = copy_for_net(&buf[7], k5_auth.data, k5_auth.length);
  3242.         else {
  3243.           debug(F100,"auth_send() KRB5 auth data too large for buffer","",0);
  3244.           k5_auth.length = 0;
  3245.         }
  3246.  
  3247.         sprintf(&buf[k5_auth.length+7], "%c%c", IAC, SE);       /* safe */
  3248.         if (deblog || tn_deb || debses) {
  3249.             int i;
  3250.             ckmakxmsg(tn_msg,TN_MSG_LEN,
  3251.                       "TELNET SENT SB ",TELOPT(TELOPT_AUTHENTICATION)," IS ",
  3252.                       AUTHTYPE_NAME(authentication_version)," ",
  3253.                       AUTHMODE_NAME(mode)," AUTH ",
  3254.                       NULL,NULL,NULL,NULL,NULL
  3255.                      );
  3256.             tn_hex(tn_msg,TN_MSG_LEN,&buf[7],k5_auth.length);
  3257.             ckstrncat(tn_msg,"IAC SE",TN_MSG_LEN);
  3258.             debug(F100,tn_msg,"",0);
  3259.             if (tn_deb || debses) tn_debug(tn_msg);
  3260.         }
  3261. #ifdef OS2
  3262.         RequestTelnetMutex( SEM_INDEFINITE_WAIT );
  3263. #endif
  3264.         ttol((CHAR *)buf, k5_auth.length+9);
  3265. #ifdef OS2
  3266.         ReleaseTelnetMutex();
  3267. #endif
  3268. #ifdef HEIMDAL
  3269.         krb5_data_free(&k5_auth);
  3270. #else /* HEIMDAL */
  3271.         krb5_free_data_contents(k5_context,&k5_auth);
  3272.         memset(&k5_auth,0,sizeof(krb5_data));
  3273. #endif /* HEIMDAL */
  3274.         break;
  3275. #endif /* KRB5 */
  3276.     }
  3277.     return AUTH_SUCCESS;
  3278. }
  3279.  
  3280. /*
  3281.  * Function: Parse authentication REPLY command
  3282.  *
  3283.  * Parameters:
  3284.  *  parsedat - the sub-command data.
  3285.  *
  3286.  *      end_sub - index of the character in the 'parsedat' array which
  3287.  *              is the last byte in a sub-negotiation
  3288.  *
  3289.  * Returns: Kerberos error code.
  3290.  */
  3291. static int
  3292. #ifdef CK_ANSIC
  3293. auth_reply(unsigned char *parsedat, int end_sub)
  3294. #else
  3295. auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3296. #endif
  3297. {
  3298.     int n = AUTH_FAILURE;
  3299.  
  3300.     if ( parsedat[2] != authentication_version ) {
  3301.         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
  3302.                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
  3303.                 AUTHTYPE_NAME(authentication_version),authentication_version);
  3304.         auth_finished(AUTH_REJECT);
  3305.         return(AUTH_FAILURE);
  3306.     }
  3307.     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
  3308.         printf("Authentication mode mismatch (%s != %s)\r\n",
  3309.                 AUTHMODE_NAME(parsedat[3]),
  3310.                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
  3311.         auth_finished(AUTH_REJECT);
  3312.         return(AUTH_FAILURE);
  3313.     }
  3314.  
  3315. #ifdef KRB4
  3316.     if (authentication_version == AUTHTYPE_KERBEROS_V4)
  3317.         n = k4_auth_reply(parsedat, end_sub);
  3318. #endif
  3319. #ifdef KRB5
  3320.     if (authentication_version == AUTHTYPE_KERBEROS_V5)
  3321.         n = k5_auth_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3322. #endif
  3323. #ifdef CK_SRP
  3324.     if (authentication_version == AUTHTYPE_SRP) {
  3325. #ifndef PRE_SRP_1_7_3
  3326.         n = new_srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3327. #else /* PRE_SRP_1_7_3 */
  3328.         n = srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3329. #endif /* PRE_SRP_1_7_3 */
  3330.     }
  3331. #endif /* SRP */
  3332. #ifdef CK_SSL
  3333.     if (authentication_version == AUTHTYPE_SSL)
  3334.         n = ssl_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3335. #endif /* SSL */
  3336. #ifdef NTLM
  3337.     if (authentication_version == AUTHTYPE_NTLM)
  3338.         n = ntlm_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  3339. #endif /* NTLM */
  3340.     return n;
  3341. }
  3342.  
  3343.  
  3344. /*
  3345.  * Function: Parse authentication IS command
  3346.  *
  3347.  * Parameters:
  3348.  *  parsedat - the sub-command data.
  3349.  *
  3350.  *      end_sub - index of the character in the 'parsedat' array which
  3351.  *              is the last byte in a sub-negotiation
  3352.  *
  3353.  * Returns: Kerberos error code.
  3354.  */
  3355. static int
  3356. #ifdef CK_ANSIC
  3357. auth_is(unsigned char *parsedat, int end_sub)
  3358. #else
  3359. auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3360. #endif
  3361. {
  3362.     int n = AUTH_FAILURE;
  3363.  
  3364.     if ( parsedat[2] == AUTHTYPE_NULL ) {
  3365.         auth_finished(AUTH_REJECT);
  3366.         return(AUTH_FAILURE);
  3367.     }
  3368.  
  3369.     /*
  3370.      *  If CLIENT_CHOOSE_ONCE is selected the server will not allow the
  3371.      *  client to switch to an alternate authentication method if the one
  3372.      *  it originally selected fails.  (ie, if the host's SRP parameters
  3373.      *  are invalid.)  However, I think this is a bit of a security risk
  3374.      *  since allowing that functionality means that it is impossible to
  3375.      *  detect if an attack is being carried out on
  3376.      */
  3377. #define CLIENT_CHOOSE_ONCE
  3378. #ifdef CLIENT_CHOOSE_ONCE
  3379.     if ( authentication_version == AUTHTYPE_AUTO )
  3380. #endif /* CLIENT_CHOOSE_ONCE */
  3381.     {
  3382.         /* this block of code needs to check the initial parameters */
  3383.         /* to ensure that those returned match one of the sets that */
  3384.         /* were sent to the client in the first place.              */
  3385.  
  3386.         int i=0;
  3387.         for ( i=4; str_request[i] != IAC ; i+=2) {
  3388.             if (str_request[i] == parsedat[2] &&
  3389.                  str_request[i+1] == parsedat[3])
  3390.                 break;
  3391.         }
  3392.  
  3393.         if ( str_request[i] == IAC ) {
  3394.             printf("Invalid authentication type pair (%s,%s)\r\n",
  3395.                     AUTHTYPE_NAME(parsedat[2]),
  3396.                     AUTHMODE_NAME(parsedat[3]));
  3397.             auth_finished(AUTH_REJECT);
  3398.             return(AUTH_FAILURE);
  3399.         }
  3400.  
  3401.         if (authentication_version != parsedat[2]) {
  3402.             authentication_version = parsedat[2];
  3403.             auth_how = (parsedat[3] & AUTH_HOW_MASK);
  3404.             auth_crypt = (parsedat[3] & AUTH_ENCRYPT_MASK);
  3405.             auth_fwd = (parsedat[3] & INI_CRED_FWD_MASK);
  3406.             debug(F111,"auth_is","authentication_version",
  3407.                   authentication_version);
  3408.             debug(F111,"auth_is","auth_how",auth_how);
  3409.             debug(F111,"auth_is","auth_crypt",auth_crypt);
  3410.             debug(F111,"auth_is","auth_fwd",auth_fwd);
  3411.         }
  3412.     }
  3413.  
  3414. #ifdef CLIENT_CHOOSE_ONCE
  3415.     if ( parsedat[2] != authentication_version ) {
  3416.         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
  3417.                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
  3418.                 AUTHTYPE_NAME(authentication_version),authentication_version);
  3419.         auth_finished(AUTH_REJECT);
  3420.         return(AUTH_FAILURE);
  3421.     }
  3422.     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
  3423.         printf("Authentication mode mismatch (%s != %s)\r\n",
  3424.                 AUTHMODE_NAME(parsedat[3]),
  3425.                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
  3426.         auth_finished(AUTH_REJECT);
  3427.         return(AUTH_FAILURE);
  3428.     }
  3429. #endif /* CLIENT_CHOOSE_ONCE */
  3430.  
  3431.     switch (authentication_version) {
  3432. #ifdef KRB4
  3433.     case AUTHTYPE_KERBEROS_V4:
  3434.         n = k4_auth_is(parsedat, end_sub);
  3435.         break;
  3436. #endif
  3437. #ifdef KRB5
  3438.     case AUTHTYPE_KERBEROS_V5:
  3439.         n = k5_auth_is(parsedat[3],parsedat, end_sub);
  3440.         break;
  3441. #endif
  3442. #ifdef CK_SRP
  3443.     case AUTHTYPE_SRP:
  3444. #ifndef PRE_SRP_1_7_3
  3445.         n = new_srp_is(parsedat[3], parsedat, end_sub);
  3446. #else /* PRE_SRP_1_7_3 */
  3447.         n = srp_is(parsedat[3], parsedat, end_sub);
  3448. #endif /* PRE_SRP_1_7_3 */
  3449.         break;
  3450. #endif /* SRP */
  3451. #ifdef CK_SSL
  3452.     case AUTHTYPE_SSL:
  3453.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3454.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3455.         n = ssl_is(parsedat, end_sub);
  3456.         break;
  3457. #endif /* SSL */
  3458. #ifdef NTLM
  3459.     case AUTHTYPE_NTLM:
  3460.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3461.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3462.         n = ntlm_is(parsedat, end_sub);
  3463.         break;
  3464. #endif /* NTLM */
  3465.     case AUTHTYPE_NULL:
  3466.     default:
  3467.         n = AUTH_FAILURE;
  3468.     }
  3469.     debug(F111,"auth_is","n",n);
  3470.     return n;
  3471. }
  3472.  
  3473. /*
  3474.  * Function: Parse authentication NAME command
  3475.  *
  3476.  * Parameters:
  3477.  *  parsedat - the sub-command data.
  3478.  *
  3479.  *      end_sub - index of the character in the 'parsedat' array which
  3480.  *              is the last byte in a sub-negotiation
  3481.  *
  3482.  * Returns: Kerberos error code.
  3483.  */
  3484. static int
  3485. #ifdef CK_ANSIC
  3486. auth_name(unsigned char *parsedat, int end_sub)
  3487. #else
  3488. auth_name(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3489. #endif
  3490. {
  3491.     int len = (end_sub-2) > 63 ? 63 : (end_sub-2);
  3492.     if ( len > 0 && (len + 1) < sizeof(szUserNameRequested)) {
  3493.         memcpy(szUserNameRequested,&parsedat[2],len);           /* safe */
  3494.         szUserNameRequested[len] = '\0';
  3495.     } else
  3496.       szUserNameRequested[0] = '\0';
  3497.     debug(F111,"auth_name szUserNameRequested",szUserNameRequested,len);
  3498.     return(AUTH_SUCCESS);
  3499. }
  3500.  
  3501. /*
  3502.  * Function: Parse the athorization sub-options and reply.
  3503.  *
  3504.  * Parameters:
  3505.  *      parsedat - sub-option string to parse.
  3506.  *
  3507.  *      end_sub - last charcter position in parsedat.
  3508.  */
  3509. int
  3510. auth_parse(unsigned char *parsedat, int end_sub)
  3511. {
  3512.     int rc = AUTH_FAILURE;
  3513.     switch (parsedat[1]) {
  3514.     case TELQUAL_SEND:
  3515.         rc = auth_send(parsedat, end_sub);
  3516.         break;
  3517.     case TELQUAL_REPLY:
  3518.         rc= auth_reply(parsedat, end_sub);
  3519.         break;
  3520.     case TELQUAL_IS:
  3521.         rc = auth_is(parsedat, end_sub);
  3522.         break;
  3523.     case TELQUAL_NAME:
  3524.         rc = auth_name(parsedat, end_sub);
  3525.         break;
  3526.     }
  3527.     debug(F111,"auth_parse","rc",rc);
  3528.     return(rc);
  3529. }
  3530.  
  3531.  
  3532. /*
  3533.  * Function: Initialization routine called kstream encryption system.
  3534.  *
  3535.  * Parameters:
  3536.  *  data - user data.
  3537.  */
  3538. int
  3539. #ifdef CK_ANSIC
  3540. auth_init(kstream ks)
  3541. #else
  3542. auth_init(ks) kstream_ptr ks;
  3543. #endif
  3544. {
  3545. #ifdef FORWARD
  3546.     forwarded_tickets = 0;  /* were tickets forwarded? */
  3547. #endif /* FORWARD */
  3548. #ifdef CK_ENCRYPTION
  3549.     encrypt_init(ks,cx_type);
  3550. #endif
  3551.     return 0;
  3552. }
  3553.  
  3554.  
  3555. /*
  3556.  * Function: Destroy routine called kstream encryption system.
  3557.  *
  3558.  * Parameters:
  3559.  *  data - user data.
  3560.  */
  3561. VOID
  3562. #ifdef CK_ANSIC
  3563. auth_destroy(void)
  3564. #else
  3565. auth_destroy()
  3566. #endif
  3567. {
  3568. }
  3569.  
  3570.  
  3571. /*
  3572.  * Function: Callback to encrypt a block of characters
  3573.  *
  3574.  * Parameters:
  3575.  *  out - return as pointer to converted buffer.
  3576.  *
  3577.  *  in - the buffer to convert
  3578.  *
  3579.  * Returns: number of characters converted.
  3580.  */
  3581. int
  3582. #ifdef CK_ANSIC
  3583. auth_encrypt(struct kstream_data_block *out,
  3584.              struct kstream_data_block *in)
  3585. #else
  3586. auth_encrypt(out,in)
  3587.     struct kstream_data_block *out; struct kstream_data_block *in;
  3588. #endif
  3589. {
  3590.     out->ptr = in->ptr;
  3591.  
  3592.     out->length = in->length;
  3593.  
  3594.     return(out->length);
  3595. }
  3596.  
  3597.  
  3598. /*
  3599.  * Function: Callback to decrypt a block of characters
  3600.  *
  3601.  * Parameters:
  3602.  *  out - return as pointer to converted buffer.
  3603.  *
  3604.  *  in - the buffer to convert
  3605.  *
  3606.  * Returns: number of characters converted.
  3607.  */
  3608. int
  3609. #ifdef CK_ANSIC
  3610. auth_decrypt(struct kstream_data_block *out,
  3611.              struct kstream_data_block *in)
  3612. #else
  3613. auth_decrypt(out,in)
  3614.     struct kstream_data_block *out; struct kstream_data_block *in;
  3615. #endif
  3616. {
  3617.     out->ptr = in->ptr;
  3618.  
  3619.     out->length = in->length;
  3620.  
  3621.     return(out->length);
  3622. }
  3623.  
  3624. #ifdef KRB4
  3625. #ifdef NT
  3626. void
  3627. ck_krb4_debug(int x)
  3628. {
  3629.     set_krb_debug(x);
  3630.     set_krb_ap_req_debug(x);
  3631. }
  3632. #endif /* NT */
  3633. int
  3634. ck_krb4_autoget_TGT(char * realm)
  3635. {
  3636.     extern struct krb_op_data krb_op;
  3637.     extern struct krb4_init_data krb4_init;
  3638.     char passwd[PWD_SZ];
  3639.     char prompt[256];
  3640.     char * saverealm=NULL;
  3641.     int  rc = -1;
  3642.     extern char * k4prprompt;
  3643.     extern char * k4pwprompt;
  3644.  
  3645.     ini_kerb();         /* Place defaults in above structs */
  3646.     passwd[0] = '\0';
  3647.  
  3648.     if ( krb4_init.principal == NULL ||
  3649.          krb4_init.principal[0] == '\0') {
  3650.         readtext(k4prprompt && k4prprompt[0] ?
  3651.                  k4prprompt :
  3652.                  "Kerberos 4 Principal: ",
  3653.                  passwd,PWD_SZ-1);
  3654.         if ( passwd[0] )
  3655.             makestr(&krb4_init.principal,passwd);
  3656.         else
  3657.             return(0);
  3658.     }
  3659.  
  3660.     /* Save realm in init structure so it can be restored */
  3661.     if ( realm ) {
  3662.         saverealm = krb4_init.realm;
  3663.         krb4_init.realm = realm;
  3664.     }
  3665.  
  3666.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  3667.  
  3668.         if ( k4pwprompt && k4pwprompt[0] &&
  3669.              (strlen(k4pwprompt) + strlen(krb4_init.principal) +
  3670.                strlen(krb4_init.realm) - 4) < sizeof(prompt)) {
  3671.             sprintf(prompt,k4pwprompt,krb4_init.principal,krb4_init.realm);
  3672.         } else
  3673.             ckmakxmsg(prompt,sizeof(prompt),
  3674.                   "Kerberos 4 Password for ",krb4_init.principal,"@",
  3675.                   krb4_init.realm,": ",
  3676.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  3677.         readpass(prompt,passwd,PWD_SZ-1);
  3678.     } else {
  3679.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  3680. #ifdef OS2
  3681.         if ( pwcrypt )
  3682.             ck_encrypt((char *)passwd);
  3683. #endif /* OS2 */
  3684.     }
  3685.  
  3686.     if ( passwd[0] ) {
  3687.         makestr(&krb4_init.password,passwd);
  3688.         rc = ck_krb4_initTGT(&krb_op, &krb4_init);
  3689.         free(krb4_init.password);
  3690.         krb4_init.password = NULL;
  3691.     }
  3692.  
  3693.     krb4_init.password = NULL;
  3694.     memset(passwd,0,PWD_SZ);
  3695.  
  3696.     /* restore realm to init structure if needed */
  3697.     if ( saverealm )
  3698.         krb4_init.realm = saverealm;
  3699.     return(rc == 0);
  3700. }
  3701.  
  3702. char *
  3703. ck_krb4_realmofhost(char *host)
  3704. {
  3705.     return (char *)krb_realmofhost(host);
  3706. }
  3707.  
  3708. /*
  3709.  *
  3710.  * K4_auth_send - gets authentication bits we need to send to KDC.
  3711.  *
  3712.  * Result is left in auth
  3713.  *
  3714.  * Returns: 0 on failure, 1 on success
  3715.  */
  3716. static int
  3717. #ifdef CK_ANSIC
  3718. k4_auth_send(void)
  3719. #else
  3720. k4_auth_send()
  3721. #endif
  3722. {
  3723.     int r=0;                                    /* Return value */
  3724.     char instance[INST_SZ+1]="";
  3725.     char *realm=NULL;
  3726.     char tgt[4*REALM_SZ+1];
  3727.  
  3728.     memset(instance, 0, sizeof(instance));
  3729.  
  3730. #ifdef COMMENT
  3731.     /* we only need to call krb_get_phost if the hostname */
  3732.     /* is not fully qualified.  But we have already done  */
  3733.     /* this in netopen() call.  This will save a round of */
  3734.     /* DNS queries.                                       */
  3735.     debug(F110,"k4_auth_send","krb_get_phost",0);
  3736.     if (realm = (char *)krb_get_phost(szHostName)) {
  3737.         ckstrncpy(instance, realm, INST_SZ);
  3738.     }
  3739. #else /* COMMENT */
  3740.     {
  3741.         char *p;
  3742.         ckstrncpy(instance, szHostName, INST_SZ);
  3743.         for ( p=instance; *p && *p != '.' ; p++ );
  3744.         *p = '\0';
  3745.     }
  3746. #endif /* COMMENT */
  3747.  
  3748.     debug(F110,"k4_auth_send","krb_get_realmofhost",0);
  3749.     realm = (char *)krb_realmofhost(szHostName);
  3750.  
  3751.     if (!realm) {
  3752.         strcpy(strTmp, "Can't find realm for host \"");
  3753.         ckstrncat(strTmp, szHostName,AUTHTMPBL);
  3754.         ckstrncat(strTmp, "\"",AUTHTMPBL);
  3755.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3756.         krb4_errno = r;
  3757.         makestr(&krb4_errmsg,strTmp);
  3758.         return(0);
  3759.     }
  3760.  
  3761.     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",realm,"@",realm);
  3762.     r = ck_krb4_tkt_isvalid(tgt);
  3763.  
  3764.     if ( r <= 0 && krb4_autoget )
  3765.         ck_krb4_autoget_TGT(realm);
  3766.  
  3767.     debug(F110,"k4_auth_send","krb_mk_req",0);
  3768.     r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3769.                     instance, realm, 0);
  3770.  
  3771.     if (r == 0) {
  3772.         debug(F110,"k4_auth_send","krb_get_cred",0);
  3773.         r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3774.                           instance, realm, (CREDENTIALS *)&cred);
  3775.         if (r)
  3776.             debug(F111,"k4_auth_send","krb_get_cred() failed",r);
  3777.     }
  3778.     else
  3779.         debug(F111,"k4_auth_send","krb_mk_req() failed",r);
  3780.  
  3781.     if (r) {
  3782.         strcpy(strTmp, "Can't get \"");
  3783.         ckstrncat(strTmp,
  3784.                   krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,AUTHTMPBL);
  3785.         if (instance[0] != 0) {
  3786.             ckstrncat(strTmp, ".",AUTHTMPBL);
  3787.             ckstrncat(strTmp, instance,AUTHTMPBL);
  3788.         }
  3789.         ckstrncat(strTmp, "@",AUTHTMPBL);
  3790.         ckstrncat(strTmp, realm,AUTHTMPBL);
  3791.         ckstrncat(strTmp, "\" ticket\r\n  ",AUTHTMPBL);
  3792.         ckstrncat(strTmp, (char *)krb_get_err_text_entry(r),AUTHTMPBL);
  3793.         debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
  3794.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3795.         krb4_errno = r;
  3796.         makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3797.         return(0);
  3798.     }
  3799.  
  3800. #ifdef OS2
  3801.     if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
  3802.         ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
  3803.     }
  3804. #endif /* OS2 */
  3805.     krb4_errno = r;
  3806.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3807.     debug(F110,"k4_auth_send",krb4_errmsg,0);
  3808.     return(1);
  3809. }
  3810.  
  3811. /*
  3812.  * Function: K4 parse authentication reply command
  3813.  *
  3814.  * Parameters:
  3815.  *  parsedat - the sub-command data.
  3816.  *
  3817.  *  end_sub - index of the character in the 'parsedat' array which
  3818.  *              is the last byte in a sub-negotiation
  3819.  *
  3820.  * Returns: Kerberos error code.
  3821.  */
  3822. static int
  3823. #ifdef CK_ANSIC
  3824. k4_auth_reply(unsigned char *parsedat, int end_sub)
  3825. #else
  3826. k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3827. #endif
  3828. {
  3829. #ifdef CK_ENCRYPTION
  3830.     Session_Key skey;
  3831. #ifdef MIT_CURRENT
  3832.     krb5_data kdata;
  3833.     krb5_enc_data encdata;
  3834.     krb5_error_code code;
  3835. #endif /* MIT_CURRENT */
  3836. #endif
  3837.     time_t t;
  3838.     int x;
  3839.     int i;
  3840.  
  3841.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  3842.         auth_finished(AUTH_REJECT);
  3843.         return AUTH_FAILURE;
  3844.     }
  3845.  
  3846.     if (parsedat[4] == KRB_REJECT) {
  3847.         strTmp[0] = 0;
  3848.  
  3849.         for (i = 5; i <= end_sub; i++) {
  3850.             if (parsedat[i] == IAC)
  3851.                 break;
  3852.             strTmp[i-5] = parsedat[i];
  3853.             strTmp[i-4] = 0;
  3854.         }
  3855.  
  3856.         if (!strTmp[0])
  3857.             strcpy(strTmp, "Authentication rejected by remote machine!");
  3858.         printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
  3859.         krb4_errno = -1;
  3860.         makestr(&krb4_errmsg,strTmp);
  3861.         auth_finished(AUTH_REJECT);
  3862.         return AUTH_FAILURE;
  3863.     }
  3864.  
  3865.     if (parsedat[4] == KRB_ACCEPT) {
  3866.         int net_len;
  3867.         if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
  3868.             ckmakmsg(strTmp,sizeof(strTmp),"Kerberos V4 accepts you as ",
  3869.                       szUserName,NULL,NULL);
  3870.             printf("%s\r\n",strTmp);
  3871.             accept_complete = 1;
  3872.             krb4_errno = 0;
  3873.             makestr(&krb4_errmsg,strTmp);
  3874.             auth_finished(AUTH_USER);
  3875.             return AUTH_SUCCESS;
  3876.         }
  3877.  
  3878.         if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
  3879.             printf("Kerberos V4 authentication failed!\r\n");
  3880.             ckstrncpy(strTmp,
  3881.         "Kerberos V4 accepted you, but didn't provide mutual authentication",
  3882.                        sizeof(strTmp));
  3883.             printf("%s\r\n",strTmp);
  3884.             krb4_errno = -1;
  3885.             makestr(&krb4_errmsg,strTmp);
  3886.             auth_finished(AUTH_REJECT);
  3887.             return AUTH_FAILURE;
  3888.         }
  3889.  
  3890. #ifndef REMOVE_FOR_EXPORT
  3891. #ifdef CK_ENCRYPTION
  3892.         SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
  3893.  
  3894.         /* We have sent the decrypted session key to the host as a challenge */
  3895.         /* now encrypt it to restore it to its original valid DES key value */
  3896. #ifdef MIT_CURRENT
  3897.         kdata.data = k4_session_key;
  3898.         kdata.length = 8;
  3899.  
  3900.         encdata.ciphertext.data = k4_session_key;
  3901.         encdata.ciphertext.length = 8;
  3902.         encdata.enctype = ENCTYPE_UNKNOWN;
  3903.  
  3904.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
  3905.                                    0, 0, &kdata, &encdata)) {
  3906.             com_err("k4_auth_reply", code,
  3907.                      "while encrypting session_key");
  3908.             auth_finished(AUTH_REJECT);
  3909.             return AUTH_FAILURE;
  3910.         }
  3911. #else /* MIT_CURRENT */
  3912. #ifdef NT
  3913.         des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
  3914. #else /* NT */
  3915.         des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
  3916. #endif /* NT */
  3917.         hexdump(
  3918.             "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
  3919.              k4_session_key,
  3920.              8
  3921.                 );
  3922. #endif /* MIT_CURRENT */
  3923.  
  3924. #ifdef CK_SSL
  3925.         if (!(ssl_active_flag || tls_active_flag))
  3926. #endif /* CK_SSL */
  3927.         {
  3928.         /* And then use it to configure the encryption state machine. */
  3929.             skey.type = SK_DES;
  3930.             skey.length = 8;
  3931.             skey.data = k4_session_key;
  3932.             encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  3933.         }
  3934. #endif /* ENCRYPTION */
  3935. #endif /* REMOVE_FOR_EXPORT */
  3936.         accept_complete = 1;
  3937.         ckmakmsg(strTmp,sizeof(strTmp),
  3938.                  "Kerberos V4 accepts you as ",szUserName,NULL,NULL);
  3939.         printf("%s\r\n",strTmp);
  3940.         krb4_errno = 0;
  3941.         makestr(&krb4_errmsg,strTmp);
  3942.         auth_finished(AUTH_USER);
  3943.         return AUTH_SUCCESS;
  3944.     }
  3945.  
  3946.     if (parsedat[4] == KRB4_RESPONSE) {
  3947.         if (end_sub < 12) {
  3948.             auth_finished(AUTH_REJECT);
  3949.             return AUTH_FAILURE;
  3950.         }
  3951.  
  3952.         hexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
  3953. #ifdef CK_ENCRYPTION
  3954.         hexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
  3955.  
  3956.         /* The datablock returned from the host should match the value */
  3957.         /* we stored in k4_challenge.                                  */
  3958.         if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
  3959.             printf("Kerberos V4 authentication failed!\r\n%s\r\n",
  3960.             "Remote machine is being impersonated!");
  3961.             krb4_errno = -1;
  3962.             makestr(&krb4_errmsg,"Remote machine is being impersonated!");
  3963.             auth_finished(AUTH_REJECT);
  3964.             return AUTH_FAILURE;
  3965.         }
  3966. #else /* ENCRYPTION */
  3967.         makestr(&krb4_errmsg,"Kermit built without support for encryption.");
  3968.         return AUTH_FAILURE;
  3969. #endif /* ENCRYPTION */
  3970.         mutual_complete = 1;
  3971.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  3972.                    sizeof(strTmp));
  3973.         printf("%s\r\n",strTmp);
  3974.         krb4_errno = 0;
  3975.         makestr(&krb4_errmsg,strTmp);
  3976.         auth_finished(AUTH_USER);
  3977.         return AUTH_SUCCESS;
  3978.     }
  3979.     auth_finished(AUTH_REJECT);
  3980.     return AUTH_FAILURE;
  3981. }
  3982.  
  3983. /*
  3984.  * Function: K4 parse authentication IS command
  3985.  *
  3986.  * Parameters:
  3987.  *  parsedat - the sub-command data.
  3988.  *
  3989.  *  end_sub - index of the character in the 'parsedat' array which
  3990.  *            is the last byte in a sub-negotiation
  3991.  *
  3992.  * Returns: Kerberos error code.
  3993.  */
  3994.  
  3995. static int
  3996. #ifdef CK_ANSIC
  3997. k4_auth_is(unsigned char *parsedat, int end_sub)
  3998. #else
  3999. k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  4000. #endif
  4001. {
  4002. #ifdef CK_ENCRYPTION
  4003.     Session_Key skey;
  4004. #ifdef MIT_CURRENT
  4005.     Block datablock, tmpkey;
  4006.     krb5_data kdata;
  4007.     krb5_enc_data encdata;
  4008.     krb5_error_code code;
  4009. #else /* MIT_CURRENT */
  4010.     Block datablock;
  4011. #endif /* MIT_CURRENT */
  4012. #endif  /* ENCRYPTION */
  4013.     char realm[REALM_SZ+1];
  4014.     char instance[INST_SZ];
  4015.     int r = 0;
  4016.     char * data = &parsedat[5];
  4017.     int    cnt = end_sub - 5;
  4018.     extern char myipaddr[];
  4019.     struct hostent *host;
  4020.     struct in_addr inaddr;
  4021.     int i;
  4022.  
  4023.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  4024.         debug(F110,"k4_auth_is","Not kerberos v4",0);
  4025.         auth_finished(AUTH_REJECT);
  4026.         return AUTH_FAILURE;
  4027.     }
  4028.  
  4029.     switch (parsedat[4]) {
  4030.     case KRB_AUTH:
  4031.         debug(F110,"k4_auth_is","KRB_AUTH",0);
  4032.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ+1);
  4033.         if (realm[0] == '\0') {
  4034.             SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
  4035.             printf("\r\n? Kerberos 4 - No Local Realm\r\n");
  4036.             debug(F110,"k4_auth_is","No local realm",0);
  4037.             krb4_errno = -1;
  4038.             makestr(&krb4_errmsg,"No local realm");
  4039.             auth_finished(AUTH_REJECT);
  4040.             return AUTH_FAILURE;
  4041.         }
  4042.         debug(F110,"k4_auth_is",realm,0);
  4043.         if ( cnt < sizeof(k4_auth.dat) ) {
  4044.             k4_auth.length = cnt;
  4045.             memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
  4046.         } else
  4047.             k4_auth.length = 0;
  4048.         hexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
  4049.  
  4050.         /* Get Instance */
  4051.         inaddr.s_addr = inet_addr(myipaddr);
  4052.         host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
  4053.         if ( host ) {
  4054. #ifdef HADDRLIST
  4055.             host = ck_copyhostent(host);
  4056. #endif /* HADDRLIST */
  4057.             ckstrncpy(instance,host->h_name,INST_SZ);
  4058.             for ( i=0;i<INST_SZ;i++ ) {
  4059.                 if ( instance[i] == '.' )
  4060.                     instance[i] = '\0';
  4061.                 else
  4062.                     instance[i] = tolower(instance[i]);
  4063.             }
  4064.         } else {
  4065.             instance[0] = '*';
  4066.             instance[1] = 0;
  4067.         }
  4068.  
  4069.         if (r = krb_rd_req(&k4_auth,
  4070.                             krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  4071.                             instance, 0, &k4_adat, k4_keytab)) {
  4072.  
  4073.             hexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
  4074.             krb_kntoln(&k4_adat, k4_name);
  4075.             ckmakmsg(strTmp,sizeof(strTmp),
  4076.                      "Kerberos failed him as ", k4_name,NULL,NULL);
  4077.             printf("%s\r\n",strTmp);
  4078.             krb4_errno = r;
  4079.             makestr(&krb4_errmsg,strTmp);
  4080.             SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
  4081.             auth_finished(AUTH_REJECT);
  4082.             return AUTH_FAILURE;
  4083.         }
  4084.  
  4085. #ifdef CK_ENCRYPTION
  4086.         memcpy((void *)k4_session_key, (void *)k4_adat.session,
  4087.                 sizeof(Block));                 /* safe */
  4088.         hexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
  4089. #endif /* ENCRYPTION */
  4090.         krb_kntoln(&k4_adat, k4_name);
  4091.  
  4092.         ckstrncpy(szUserNameAuthenticated,k4_name,UIDBUFLEN);
  4093.         if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
  4094.             SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
  4095.             if ( !strcmp(k4_name,szUserNameRequested) )
  4096.                 auth_finished(AUTH_VALID);
  4097.             else
  4098.                 auth_finished(AUTH_USER);
  4099.             accept_complete = 1;
  4100.         }
  4101.         else {
  4102.             SendK4AuthSB(KRB_REJECT,
  4103.                   (void *)"user is not authorized", -1);
  4104.             auth_finished(AUTH_REJECT);
  4105.             krb4_errno = r;
  4106.             makestr(&krb4_errmsg,"user is not authorized");
  4107.             return(AUTH_FAILURE);
  4108.         }
  4109.         break;
  4110.  
  4111.     case KRB4_CHALLENGE:
  4112.         debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
  4113. #ifndef CK_ENCRYPTION
  4114.         SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  4115. #else   /* ENCRYPTION */
  4116.         if (!VALIDKEY(k4_session_key)) {
  4117.             /*
  4118.             * We don't have a valid session key, so just
  4119.             * send back a response with an empty session
  4120.             * key.
  4121.             */
  4122.             SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  4123.             mutual_complete = 1;
  4124.             break;
  4125.         }
  4126.  
  4127.         /*
  4128.         * Initialize the random number generator since it's
  4129.         * used later on by the encryption routine.
  4130.         */
  4131. #ifdef MIT_CURRENT
  4132.         kdata.data = k4_session_key;
  4133.         kdata.length = 8;
  4134.  
  4135.         if (code = krb5_c_random_seed(k5_context, &kdata)) {
  4136.             com_err("k4_auth_is", code,
  4137.                      "while seeding random number generator");
  4138.             auth_finished(AUTH_REJECT);
  4139.             return AUTH_FAILURE;
  4140.         }
  4141.  
  4142.         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
  4143.         /*
  4144.         * Take the received encrypted challenge, and encrypt
  4145.         * it again to get a unique session_key for the
  4146.         * ENCRYPT option.
  4147.         */
  4148.         k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  4149.         k4_krbkey.length = 8;
  4150.         k4_krbkey.contents = k4_session_key;
  4151.  
  4152.         kdata.data = datablock;
  4153.         kdata.length = 8;
  4154.  
  4155.         encdata.ciphertext.data = tmpkey;
  4156.         encdata.ciphertext.length = 8;
  4157.         encdata.enctype = ENCTYPE_UNKNOWN;
  4158.  
  4159.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  4160.                                    &kdata, &encdata)) {
  4161.             com_err("k4_auth_is", code, "while encrypting random key");
  4162.             auth_finished(AUTH_REJECT);
  4163.             return AUTH_FAILURE;
  4164.         }
  4165.  
  4166. #ifdef CK_SSL
  4167.         if (!(ssl_active_flag || tls_active_flag))
  4168. #endif /* CK_SSL */
  4169.         {
  4170.             skey.type = SK_DES;
  4171.             skey.length = 8;
  4172.             skey.data = tmpkey;
  4173.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4174.         }
  4175.         /*
  4176.         * Now decrypt the received encrypted challenge,
  4177.         * increment by one, re-encrypt it and send it back.
  4178.         */
  4179.         encdata.ciphertext.data = datablock;
  4180.         encdata.ciphertext.length = 8;
  4181.         encdata.enctype = ENCTYPE_UNKNOWN;
  4182.  
  4183.         kdata.data = k4_challenge;
  4184.         kdata.length = 8;
  4185.  
  4186.         if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  4187.                                    &encdata, &kdata)) {
  4188.             com_err("k4_auth_is", code, "while decrypting challenge");
  4189.             auth_finished(AUTH_REJECT);
  4190.             return AUTH_FAILURE;
  4191.         }
  4192. #else /* MIT_CURRENT */
  4193.         des_set_random_generator_seed(k4_session_key);
  4194.         r = des_key_sched(k4_session_key, k4_sched);
  4195.         if ( r == -1 ) {
  4196.             printf("?Invalid DES key specified in credentials\r\n");
  4197.             debug(F110,"auth_is CHALLENGE",
  4198.                    "invalid DES Key specified in credentials",0);
  4199.         } else if ( r == -2 ) {
  4200.             printf("?Weak DES key specified in credentials\r\n");
  4201.             debug(F110,"auth_is CHALLENGE",
  4202.                    "weak DES Key specified in credentials",0);
  4203.         } else if ( r != 0 ) {
  4204.             printf("?DES Key Schedule not set by credentials\r\n");
  4205.             debug(F110,"auth_is CHALLENGE",
  4206.                    "DES Key Schedule not set by credentials",0);
  4207.         }
  4208.         hexdump("auth_is schedule",k4_sched,8*16);
  4209.  
  4210.         memcpy((void *)datablock, (void *)data, sizeof(Block)); /* safe */
  4211.         hexdump("auth_is challege",datablock,sizeof(Block));
  4212.  
  4213.         /*
  4214.         * Take the received encrypted challenge, and encrypt
  4215.         * it again to get a unique k4_session_key for the
  4216.         * ENCRYPT option.
  4217.         */
  4218. #ifdef NT
  4219.         des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
  4220. #else /* NT */
  4221.         des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
  4222. #endif /* NT */
  4223.         hexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
  4224.                  k4_session_key,8);
  4225.  
  4226. #ifdef CK_SSL
  4227.         if (!(ssl_active_flag || tls_active_flag))
  4228. #endif /* CK_SSL */
  4229.         {
  4230.             skey.type = SK_DES;
  4231.             skey.length = 8;
  4232.             skey.data = k4_session_key;
  4233.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4234.         }
  4235.         /*
  4236.         * Now decrypt the received encrypted challenge,
  4237.         * increment by one, re-encrypt it and send it back.
  4238.         */
  4239. #ifdef NT
  4240.         des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
  4241. #else /* NT */
  4242.         des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
  4243. #endif /* NT */
  4244.         hexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
  4245.                  k4_session_key,8);
  4246. #endif /* MIT_CURRENT */
  4247.         for (r = 7; r >= 0; r--) {
  4248.             register int t;
  4249.             t = (unsigned int)k4_challenge[r] + 1;
  4250.             k4_challenge[r] = t;        /* ignore overflow */
  4251.             if (t < 256)                /* if no overflow, all done */
  4252.                 break;
  4253.         }
  4254.         hexdump("auth_is k4_challenge+1",k4_challenge,8);
  4255.  
  4256. #ifdef MIT_CURRENT
  4257.         kdata.data = k4_challenge;
  4258.         kdata.length = 8;
  4259.  
  4260.         encdata.ciphertext.data = k4_challenge;
  4261.         encdata.ciphertext.length = 8;
  4262.         encdata.enctype = ENCTYPE_UNKNOWN;
  4263.  
  4264.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  4265.                                    &kdata, &encdata)) {
  4266.             com_err("k4_auth_is", code, "while decrypting challenge");
  4267.             auth_finished(AUTH_REJECT);
  4268.             return AUTH_FAILURE;
  4269.         }
  4270. #else /* MIT_CURRENT */
  4271. #ifdef NT
  4272.         des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  4273. #else /* NT */
  4274.         des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  4275. #endif /* NT */
  4276.         hexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
  4277.                  k4_challenge,8);
  4278.  
  4279. #endif /* MIT_CURRENT */
  4280.         SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
  4281. #endif  /* ENCRYPTION */
  4282.         mutual_complete = 1;
  4283.         break;
  4284.  
  4285.     default:
  4286.         if (1)
  4287.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  4288.         SendK4AuthSB(KRB_REJECT, 0, 0);
  4289.         return(AUTH_FAILURE);
  4290.     }
  4291.     krb4_errno = r;
  4292.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  4293.     return(AUTH_SUCCESS);
  4294. }
  4295. #endif /* KRB4 */
  4296.  
  4297. #ifdef KRB5
  4298. int
  4299. ck_krb5_autoget_TGT(char * realm)
  4300. {
  4301.     extern struct krb_op_data krb_op;
  4302.     extern struct krb5_init_data krb5_init;
  4303.     char passwd[PWD_SZ];
  4304.     char prompt[64];
  4305.     char * saverealm=NULL;
  4306.     int  rc = -1;
  4307.     extern char * k5prprompt;
  4308.     extern char * k5pwprompt;
  4309.  
  4310.     ini_kerb();         /* Place defaults in above structs */
  4311.     passwd[0] = '\0';
  4312.  
  4313.     if ( krb5_init.principal == NULL ||
  4314.          krb5_init.principal[0] == '\0') {
  4315.         readtext(k5prprompt && k5prprompt[0] ? k5prprompt :
  4316.                   "Kerberos 5 Principal: ",passwd,PWD_SZ-1);
  4317.         if ( passwd[0] )
  4318.             makestr(&krb5_init.principal,passwd);
  4319.         else
  4320.             return(0);
  4321.     }
  4322.  
  4323.     /* Save realm in init structure so it can be restored */
  4324.     if ( realm ) {
  4325.         saverealm = krb5_init.realm;
  4326.         krb5_init.realm = realm;
  4327.     }
  4328.  
  4329.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  4330.         if ( k5pwprompt && k5pwprompt[0] &&
  4331.              (strlen(k5pwprompt) + strlen(krb5_init.principal) +
  4332.               strlen(krb5_init.realm) - 4) < sizeof(prompt)) {
  4333.             sprintf(prompt,k5pwprompt,krb5_init.principal,krb5_init.realm);
  4334.         } else
  4335.         ckmakxmsg(prompt,sizeof(prompt),
  4336.                   k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  4337.                   "Kerberos 5 Password for ",
  4338.                   krb5_init.principal,"@",krb5_init.realm,": ",
  4339.                   NULL,NULL,NULL,NULL,NULL,NULL,NULL
  4340.                  );
  4341.         readpass(prompt,passwd,PWD_SZ-1);
  4342.     } else {
  4343.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  4344. #ifdef OS2
  4345.         if ( pwcrypt )
  4346.             ck_encrypt((char *)passwd);
  4347. #endif /* OS2 */
  4348.     }
  4349.  
  4350.     if ( passwd[0] ) {
  4351.         extern struct krb4_init_data krb4_init;
  4352.         char * savek4realm=NULL;
  4353.  
  4354.         makestr(&krb5_init.password,passwd);
  4355.  
  4356.         if ( krb5_d_getk4 ) {
  4357.             krb5_init.getk4 = 1;
  4358.             makestr(&krb4_init.principal,krb5_init.principal);
  4359.             makestr(&krb4_init.password,passwd);
  4360.             if ( realm ) {
  4361.                 savek4realm = krb4_init.realm;
  4362.                 krb4_init.realm = realm;
  4363.             }
  4364.             rc = ck_krb5_initTGT(&krb_op, &krb5_init,&krb4_init);
  4365.  
  4366.             if ( savek4realm )
  4367.                 krb4_init.realm = savek4realm;
  4368.             free(krb4_init.password);
  4369.             krb4_init.password = NULL;
  4370.         } else {
  4371.             rc = ck_krb5_initTGT(&krb_op, &krb5_init,NULL);
  4372.         }
  4373.  
  4374.         free(krb5_init.password);
  4375.         krb5_init.password = NULL;
  4376.  
  4377.         memset(passwd,0,PWD_SZ);
  4378.     }
  4379.  
  4380.     /* restore realm to init structure if needed */
  4381.     if ( saverealm )
  4382.         krb5_init.realm = saverealm;
  4383.     return(rc == 0);
  4384. }
  4385.  
  4386. static krb5_error_code
  4387. #ifdef CK_ANSIC
  4388. k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
  4389.                char * cc_name )
  4390. #else  /* CK_ANSIC */
  4391. k5_get_ccache(k5_context, p_ccache, cc_name)
  4392.     krb5_context k5_context;
  4393.     krb5_ccache * p_ccache;
  4394.     char * cc_name;
  4395. #endif /* CK_ANSIC */
  4396. {
  4397.     krb5_error_code r=0;
  4398.     char cc_tmp[CKMAXPATH+1];
  4399.     const char * def_name = NULL;
  4400.  
  4401. #ifndef HEIMDAL
  4402.     if ( cc_name ) {
  4403.         if ( strncmp("FILE:",cc_name,5) &&
  4404.              strncmp("MEMORY:",cc_name,7) &&
  4405.              strncmp("API:",cc_name,4) &&
  4406.              strncmp("STDIO:",cc_name,6))
  4407.             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",cc_name,NULL,NULL);
  4408.         else {
  4409.             ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
  4410.         }
  4411.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  4412.         if (r != 0) {
  4413.             com_err("k5_get_ccache resolving ccache",r,
  4414.                      cc_tmp);
  4415.         }
  4416.     } else if ( krb5_d_cc ) {
  4417.         if ( strncmp("FILE:",krb5_d_cc,5) &&
  4418.              strncmp("MEMORY:",krb5_d_cc,7) &&
  4419.              strncmp("API:",krb5_d_cc,4) &&
  4420.              strncmp("STDIO:",krb5_d_cc,6))
  4421.             ckmakmsg(cc_tmp,CKMAXPATH,"FILE:",krb5_d_cc,NULL,NULL);
  4422.         else {
  4423.             ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
  4424.         }
  4425.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  4426.         if (r != 0) {
  4427.             com_err("k5_get_ccache resolving ccache",r,
  4428.                      krb5_d_cc);
  4429.         }
  4430.     } else
  4431. #endif /* HEIMDAL */
  4432.     {
  4433.         if ((r = krb5_cc_default(k5_context, p_ccache))) {
  4434.             com_err("k5_get_ccache",r,"while getting default ccache");
  4435.         }
  4436.     }
  4437.         /* do not set krb5_errno/krb5_errmsg here since the value returned */
  4438.         /* is being passed internally within the krb5 functions.           */
  4439.     return(r);
  4440. }
  4441.  
  4442.  
  4443. char *
  4444. ck_krb5_realmofhost(char *host)
  4445. {
  4446.     char ** realmlist=NULL;
  4447.     krb5_context private_context=NULL;
  4448.     static char * realm = NULL;
  4449.  
  4450.     if ( !host )
  4451.         return NULL;
  4452.  
  4453.     if ( realm ) {
  4454.         free(realm);
  4455.         realm = NULL;
  4456.     }
  4457.  
  4458.     /* create private_context */
  4459.     if (krb5_init_context(&private_context)) {
  4460.         debug(F110,"ck_krb5_realmofhost()","unable to init_context",0);
  4461.         return(NULL);
  4462.     }
  4463.  
  4464.     krb5_get_host_realm(private_context,host,&realmlist);
  4465.     if (realmlist && realmlist[0]) {
  4466.         makestr(&realm,realmlist[0]);
  4467.         krb5_free_host_realm(private_context,realmlist);
  4468.         realmlist = NULL;
  4469.     }
  4470.  
  4471.     if ( private_context ) {
  4472.         krb5_free_context(private_context);
  4473.         private_context = NULL;
  4474.     }
  4475.  
  4476.     if (ckstrchr(realm,'.') == NULL) {
  4477.         int n = 0;
  4478.         char * p = host;
  4479.         while ( (p = ckstrchr(p,'.')) != NULL ) {
  4480.             n++;
  4481.             p++;
  4482.         }
  4483.         if (n == 1) {
  4484.             makestr(&realm,host);
  4485.             ckupper(realm);
  4486.         } else {
  4487.             free(realm);
  4488.             realm = NULL;
  4489.         }
  4490.     }
  4491.     return(realm);
  4492. }
  4493.  
  4494. /*
  4495.  *
  4496.  * K5_auth_send - gets authentication bits we need to send to KDC.
  4497.  *
  4498.  * Code lifted from telnet sample code in the appl directory.
  4499.  *
  4500.  * Result is left in k5_auth
  4501.  *
  4502.  * Returns: 0 on failure, 1 on success
  4503.  *
  4504.  */
  4505.  
  4506. static int
  4507. #ifdef CK_ANSIC
  4508. k5_auth_send(int how, int encrypt, int forward)
  4509. #else
  4510. k5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
  4511. #endif
  4512. {
  4513.     krb5_error_code r=0;
  4514.     krb5_ccache ccache=NULL;
  4515. #ifndef HEIMDAL
  4516.     krb5_creds creds;
  4517. #endif /* HEIMDAL */
  4518.     krb5_creds * new_creds=NULL;
  4519. #ifdef CK_ENCRYPTION
  4520.     krb5_keyblock *newkey = 0;
  4521. #endif /* CK_ENCRYPTION */
  4522.     krb5_flags ap_opts, auth_flags;
  4523.     char type_check[32];
  4524.     krb5_data checksum;
  4525.     int len=0;
  4526.     char * realm = NULL;
  4527.     char tgt[256];
  4528.  
  4529.     realm = ck_krb5_realmofhost(szHostName);
  4530.     if (!realm) {
  4531.         ckstrncpy(strTmp, "Can't find realm for host \"",AUTHTMPBL);
  4532.         ckstrncat(strTmp, szHostName,AUTHTMPBL);
  4533.         ckstrncat(strTmp, "\"",AUTHTMPBL);
  4534.         printf("?Kerberos 5 error: %s\r\n",strTmp);
  4535.         krb5_errno = KRB5_ERR_HOST_REALM_UNKNOWN;
  4536.         makestr(&krb5_errmsg,strTmp);
  4537.         return(0);
  4538.     }
  4539.  
  4540.     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  4541.     debug(F110,"k5_auth_send TGT",tgt,0);
  4542.     if ( krb5_autoget &&
  4543.          !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  4544.           (ck_krb5_is_tgt_valid() > 0)) )
  4545.         ck_krb5_autoget_TGT(realm);
  4546.  
  4547.     r = k5_get_ccache(k5_context,&ccache,NULL);
  4548.     if ( r ) {
  4549.         com_err(NULL, r, "while authorizing (0).");
  4550.         krb5_errno = r;
  4551.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4552.         return(0);
  4553.     }
  4554.  
  4555. #ifndef HEIMDAL
  4556.     memset((char *)&creds, 0, sizeof(creds));
  4557.     if (r = krb5_sname_to_principal(k5_context, szHostName,
  4558.                                 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4559.                                 KRB5_NT_SRV_HST, &creds.server)) {
  4560.         com_err(NULL, r, "while authorizing (1).");
  4561.         krb5_errno = r;
  4562.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4563.         return(0);
  4564.     }
  4565.  
  4566.     if (forward_flag) {
  4567.         if (fwd_server) {
  4568.             krb5_free_principal(k5_context,fwd_server);
  4569.             fwd_server = NULL;
  4570.         }
  4571.         krb5_copy_principal(k5_context,creds.server,&fwd_server);
  4572.     }
  4573.  
  4574.     if (r = krb5_cc_get_principal(k5_context, ccache, &creds.client)) {
  4575.         com_err(NULL, r, "while authorizing (2).");
  4576.         krb5_free_cred_contents(k5_context, &creds);
  4577.         krb5_errno = r;
  4578.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4579.         return(0);
  4580.     }
  4581.  
  4582.     if (szUserName[0] == '\0') {                /* Get user name now */
  4583.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4584.         if ( len < sizeof(szUserName) ) {
  4585.             memcpy(szUserName,
  4586.                     krb5_princ_component(k5_context, creds.client, 0)->data,
  4587.                     len);                       /* safe */
  4588.         } else
  4589.             len = 0;
  4590.         szUserName[len] = '\0';
  4591.     } else {
  4592.         char * name = NULL;
  4593.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4594.         if ( len == strlen(szUserName) ) {
  4595.             name = krb5_princ_component(k5_context, creds.client, 0)->data;
  4596. #ifdef OS2
  4597.             if ( !strnicmp(szUserName,name,len) )
  4598.                 memcpy(szUserName,name,len);    /* safe */
  4599. #endif /* OS2 */
  4600.         }
  4601.     }
  4602.  
  4603.     /* Not sure if this is necessary anymore.  What impact does it have
  4604.      * on Win2000 TGTs that use DES_CBC_MD5 or RC4_HMAC?
  4605.      *
  4606.      * This prevents using 3DES Service Tickets.
  4607.      */
  4608.     creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
  4609.     if (r = krb5_get_credentials(k5_context, 0,
  4610.                                   ccache, &creds, &new_creds)) {
  4611.         com_err(NULL, r, "while authorizing (3).");
  4612.         krb5_free_cred_contents(k5_context, &creds);
  4613.         krb5_errno = r;
  4614.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4615.         return(0);
  4616.     }
  4617. #endif /* HEIMDAL */
  4618.  
  4619.     if (auth_context) {
  4620.         krb5_auth_con_free(k5_context, auth_context);
  4621.         auth_context = 0;
  4622.     }
  4623.     if (r = krb5_auth_con_init(k5_context, &auth_context)) {
  4624.         com_err(NULL, r, "while initializing auth context");
  4625.         krb5_errno = r;
  4626.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4627.         return(0);
  4628.     }
  4629.  
  4630.     /* UPDATE for START_TLS.  AUTH_ENCRYPT_START_TLS and inclusion of */
  4631.     /* client and then server finished messages.                      */
  4632.  
  4633.     type_check[0] = AUTHTYPE_KERBEROS_V5;
  4634.     type_check[1] = AUTH_CLIENT_TO_SERVER |
  4635.         (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
  4636.         (encrypt) |
  4637.         (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
  4638. #ifdef CK_SSL
  4639.     if (encrypt == AUTH_ENCRYPT_START_TLS) {
  4640.         ssl_get_client_finished(&type_check[2],12);
  4641.         ssl_get_server_finished(&type_check[14],12);
  4642.     }
  4643. #endif /* CK_SSL */
  4644.  
  4645. #ifndef HEIMDAL
  4646.     checksum.magic = KV5M_DATA;
  4647. #endif /* HEIMDAL */
  4648.     checksum.length =
  4649. #ifdef CK_SSL
  4650.         (encrypt == AUTH_ENCRYPT_START_TLS) ? 26 :
  4651. #endif /* CK_SSL */
  4652.         2;
  4653.     checksum.data = (char *)&type_check;
  4654.  
  4655.     ap_opts = 0;
  4656.     if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
  4657.         ap_opts |= AP_OPTS_MUTUAL_REQUIRED;
  4658.  
  4659. #ifdef HEIMDAL
  4660.     r = krb5_auth_setkeytype(k5_context, auth_context, KEYTYPE_DES);
  4661.     if (r)
  4662.         com_err(NULL, r, "while setting auth keytype");
  4663.     r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context, &ttyfd);
  4664.     if (r)
  4665.         com_err(NULL, r, "while setting auth addrs");
  4666.     r = krb5_mk_req(k5_context, &auth_context, ap_opts,
  4667.                     krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4668.                     szHostName, &checksum, ccache, &k5_auth);
  4669.     if (r)
  4670.         com_err(NULL, r, "while making request");
  4671. #else /* HEIMDAL */
  4672.     auth_flags = KRB5_AUTH_CONTEXT_RET_TIME;
  4673. #ifdef CK_ENCRYPTION
  4674.     ap_opts |= AP_OPTS_USE_SUBKEY;
  4675. #endif /* CK_ENCRYPTION */
  4676. #ifdef TLS_VERIFY
  4677.     if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  4678.         auth_flags |= KRB5_AUTH_CONTEXT_DO_SEQUENCE;
  4679.         if (!krb5_d_no_addresses)
  4680.             r = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  4681.                                  KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
  4682.     }
  4683. #endif /* CK_SSL */
  4684.     krb5_auth_con_setflags(k5_context, auth_context, auth_flags);
  4685.     r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
  4686.                               &checksum, new_creds, &k5_auth);
  4687. #endif /* HEIMDAL */
  4688.  
  4689. #ifdef CK_ENCRYPTION
  4690.     if (!r) {
  4691.         r = krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
  4692.         if (r)
  4693.             r = krb5_auth_con_getkey(k5_context, auth_context, &newkey);
  4694.  
  4695.         if (k5_session_key) {
  4696.             krb5_free_keyblock(k5_context, k5_session_key);
  4697.             k5_session_key = 0;
  4698.         }
  4699.     }
  4700.     if (newkey) {
  4701.         /*
  4702.         * keep the key in our private storage, but don't use it
  4703.         * yet---see kerberos5_reply() below
  4704.         */
  4705. #ifdef HEIMDAL
  4706.         if ((newkey->keytype == ETYPE_DES_CBC_CRC) ||
  4707.              (newkey->keytype == ETYPE_DES_CBC_MD5) ||
  4708.              (newkey->keytype == ETYPE_DES_CBC_MD4))
  4709.         {
  4710.             debug(F111,"k5_auth_send()","newkey->keytype",newkey->keytype);
  4711.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4712.         }
  4713. #else /* HEIMDAL */
  4714.         /* look for all possible DES keys first - just for compatibility */
  4715.         /* other key types are much less likely to be available          */
  4716.         if ((newkey->enctype == ENCTYPE_DES_CBC_CRC) ||
  4717.              (newkey->enctype == ENCTYPE_DES_CBC_MD5) ||
  4718.              (newkey->enctype == ENCTYPE_DES_CBC_MD4))
  4719.         {
  4720.             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
  4721.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4722.         }
  4723.         else if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
  4724.                  (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
  4725.         {
  4726.             /* use the session key in credentials instead */
  4727.             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
  4728.                    new_creds->keyblock.enctype);
  4729.             krb5_copy_keyblock(k5_context,
  4730.                                 &new_creds->keyblock, &k5_session_key);
  4731.         }
  4732.         else if (newkey->enctype != 0)
  4733.         {
  4734.             debug(F111,"k5_auth_send()","newkey->enctype",newkey->enctype);
  4735.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4736.         }
  4737.         else if (new_creds->keyblock.enctype != 0)
  4738.         {
  4739.             /* use the session key in credentials instead */
  4740.             debug(F111,"k5_auth_send()","new_creds->keyblock.enctype",
  4741.                    new_creds->keyblock.enctype);
  4742.             krb5_copy_keyblock(k5_context,
  4743.                                 &new_creds->keyblock, &k5_session_key);
  4744.         }
  4745.         else {
  4746.             debug(F110,"k5_auth_send()","NO KEY in newkey",0);
  4747.         }
  4748. #endif /* HEIMDAL */
  4749.         krb5_free_keyblock(k5_context, newkey);
  4750.     }
  4751. #endif /* CK_ENCRYPTION */
  4752. #ifndef HEIMDAL
  4753.     krb5_free_cred_contents(k5_context, &creds);
  4754.     krb5_free_creds(k5_context, new_creds);
  4755. #endif /* HEIMDAL */
  4756.     krb5_cc_close(k5_context,ccache);
  4757.  
  4758.     if (r) {
  4759.         com_err(NULL, r, "while authorizing (4).");
  4760.         krb5_errno = r;
  4761.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4762.         return(0);
  4763.     }
  4764.     krb5_errno = 0;
  4765.     makestr(&krb5_errmsg,"OK");
  4766.     return(1);
  4767. }
  4768.  
  4769. /*
  4770.  * K5_auth_reply -- checks the reply for mutual authentication.
  4771.  */
  4772. static int
  4773. #ifdef CK_ANSIC
  4774. k5_auth_reply(int how, unsigned char *data, int cnt)
  4775. #else
  4776. k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  4777. #endif
  4778. {
  4779. #ifdef CK_ENCRYPTION
  4780.     Session_Key skey;
  4781. #endif /* CK_ENCRYPTION */
  4782.  
  4783.     data += 4;                                  /* Point to status byte */
  4784.     cnt -=5;
  4785.  
  4786.     switch (*data++) {
  4787.     case KRB_REJECT:
  4788.         if (cnt > 0) {
  4789.             char *s;
  4790.             int len;
  4791.             ckstrncpy(strTmp,"Kerberos V5 refuses authentication because\r\n",
  4792.                       sizeof(strTmp));
  4793.             len = strlen(strTmp);
  4794.             if ( len + cnt < sizeof(strTmp) ) {
  4795.                 s = strTmp + strlen(strTmp);
  4796.                 memcpy(s, data, cnt);           /* safe */
  4797.                 s[cnt] = 0;
  4798.             }
  4799.         } else
  4800.             ckstrncpy(strTmp,"Kerberos V5 refuses authentication",
  4801.                       sizeof(strTmp));
  4802.         krb5_errno = -1;
  4803.         makestr(&krb5_errmsg,strTmp);
  4804.         printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4805.         auth_finished(AUTH_REJECT);
  4806.         return AUTH_FAILURE;
  4807.  
  4808.     case KRB_ACCEPT:
  4809.         if (!mutual_complete) {
  4810.             if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
  4811.                 ckstrncpy(strTmp,
  4812.                           "Kerberos V5 accepted you, but didn't provide"
  4813.                           " mutual authentication",sizeof(strTmp));
  4814.                 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4815.                 krb5_errno = -1;
  4816.                 makestr(&krb5_errmsg,strTmp);
  4817.                 auth_finished(AUTH_REJECT);
  4818.                 return AUTH_FAILURE;
  4819.             }
  4820.  
  4821. #ifdef CK_ENCRYPTION
  4822.             if (k5_session_key) {
  4823.                 /* Even if the session key is 3DES, we must lie because otherwise */
  4824.                 /* we can't negotiate the proper keys for DES encryption if the   */
  4825.                 /* since the host may be requiring SK_DES key choice.             */
  4826.                 skey.type = SK_DES;
  4827.                 skey.length = 8;
  4828. #ifdef HEIMDAL
  4829.                 skey.data = k5_session_key->keyvalue.data;
  4830. #else /* HEIMDAL */
  4831.                 skey.data = k5_session_key->contents;
  4832. #endif /* HEIMDAL */
  4833.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4834.             }
  4835. #endif /* CK_ENCRYPTION */
  4836.         }
  4837.         if ( cnt > 0 ) {
  4838.             char *s;
  4839.             int len;
  4840.             ckstrncpy(strTmp,"Kerberos V5 accepts you as ",sizeof(strTmp));
  4841.             len = strlen(strTmp);
  4842.             if ( len + cnt < sizeof(strTmp) ) {
  4843.                 s = strTmp + strlen(strTmp);
  4844.                 memcpy(s,data,cnt);
  4845.                 s[cnt] = 0;
  4846.             }
  4847.         }
  4848.         accept_complete = 1;
  4849.         printf("%s\r\n",strTmp);
  4850.  
  4851. #ifdef FORWARD
  4852.         if (forward_flag
  4853. #ifdef COMMENT
  4854.              /* Marc Horowitz <marc@mit.edu> has successfully argued
  4855.                 that it is indeed safe to send Forwarded credentials
  4856.                 to an untrusted host.
  4857.               */
  4858.              && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL
  4859. #endif /* COMMENT */
  4860.              )
  4861.             kerberos5_forward();
  4862. #endif /* FORWARD */
  4863.         krb5_errno = 0;
  4864.         makestr(&krb5_errmsg,strTmp);
  4865.         auth_finished(AUTH_USER);
  4866.         return AUTH_SUCCESS;
  4867.  
  4868.     case KRB5_RESPONSE:
  4869. #ifdef TLS_VERIFY
  4870.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS &&
  4871.             !krb5_tls_verified) {
  4872.             printf(
  4873.     "Man in the middle attack detected.  Session terminated.\r\n");
  4874. #ifndef BETATEST
  4875.             netclos();
  4876. #endif /* BETATEST */
  4877.             krb5_errno = -1;
  4878.             makestr(&krb5_errmsg,"TLS not verified");
  4879.             auth_finished(AUTH_REJECT);
  4880.             return AUTH_FAILURE;
  4881.         }
  4882.         if((ssl_active_flag || tls_active_flag) &&
  4883.             (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  4884.             printf("TLS session parameters verified by Kerberos 5\r\n");
  4885.         }
  4886. #endif /* TLS_VERIFY */
  4887.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  4888.             /* the rest of the reply should contain a krb_ap_rep */
  4889.             krb5_ap_rep_enc_part *reply;
  4890.             krb5_data inbuf;
  4891.             krb5_error_code r;
  4892.  
  4893.             inbuf.length = cnt;
  4894.             inbuf.data = (char *)data;
  4895.  
  4896.             if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
  4897.                 com_err(NULL, r, "while authorizing. (5)");
  4898.                 krb5_errno = r;
  4899.                 makestr(&krb5_errmsg,error_message(krb5_errno));
  4900.                 auth_finished(AUTH_REJECT);
  4901.                 return AUTH_FAILURE;
  4902.             }
  4903.             krb5_free_ap_rep_enc_part(k5_context, reply);
  4904.  
  4905. #ifdef CK_ENCRYPTION
  4906.             if (encrypt_flag && k5_session_key) {
  4907.                 /* Even if the session key is 3DES, we must lie because otherwise */
  4908.                 /* we can't negotiate the proper keys for DES encryption if the   */
  4909.                 /* since the host may be requiring SK_DES key choice.             */
  4910.                 skey.type = SK_DES;
  4911.                 skey.length = 8;
  4912. #ifdef HEIMDAL
  4913.                 skey.data = k5_session_key->keyvalue.data;
  4914. #else /* HEIMDAL */
  4915.                 skey.data = k5_session_key->contents;
  4916. #endif /* HEIMDAL */
  4917.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4918.             }
  4919. #endif /* ENCRYPTION */
  4920.             mutual_complete = 1;
  4921.         }
  4922.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  4923.                   sizeof(strTmp));
  4924.         krb5_errno = 0;
  4925.         makestr(&krb5_errmsg,strTmp);
  4926.         printf("%s\r\n",strTmp);
  4927.         auth_finished(AUTH_USER);
  4928.         return AUTH_SUCCESS;
  4929.  
  4930. #ifdef FORWARD
  4931.     case KRB5_FORWARD_ACCEPT:
  4932.         forwarded_tickets = 1;
  4933.         ckstrncpy(strTmp,"Remote machine has accepted forwarded credentials",
  4934.                   sizeof(strTmp));
  4935.         krb5_errno = 0;
  4936.         makestr(&krb5_errmsg,strTmp);
  4937.         printf("%s\r\n",strTmp);
  4938.         return AUTH_SUCCESS;
  4939.  
  4940.     case KRB5_FORWARD_REJECT:
  4941.         forwarded_tickets = 0;
  4942.         if (cnt > 0) {
  4943.             char *s;
  4944.             int len;
  4945.             len = ckstrncpy(strTmp,
  4946.                       "Kerberos V5 refuses forwarded credentials because ",
  4947.                        sizeof(strTmp));
  4948.             if ( len + cnt < sizeof(strTmp) ) {
  4949.                 s = strTmp + strlen(strTmp);
  4950.                 memcpy(s, data, cnt);
  4951.                 s[cnt] = 0;
  4952.             }
  4953.         } else
  4954.             ckstrncpy(strTmp, "Kerberos V5 refuses forwarded credentials",
  4955.                       sizeof(strTmp));
  4956.  
  4957.         printf("%s\r\n",strTmp);
  4958.         krb5_errno = -1;
  4959.         makestr(&krb5_errmsg,strTmp);
  4960.         return AUTH_SUCCESS;
  4961. #endif  /* FORWARD */
  4962.  
  4963. #ifdef TLS_VERIFY
  4964.     case KRB5_TLS_VERIFY:
  4965.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  4966.             krb5_data reply, msg;
  4967.             char tls_verify[24];
  4968.             krb5_replay_data repdata;
  4969.             krb5_error_code r;
  4970.  
  4971.             ssl_get_server_finished(&tls_verify[0],12);
  4972.             ssl_get_client_finished(&tls_verify[12],12);
  4973.  
  4974.             reply.data = data;
  4975.             reply.length = cnt;
  4976.  
  4977.             if (!krb5_d_no_addresses)
  4978.                 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  4979.                                   KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR);
  4980.  
  4981.             if (r = krb5_rd_safe(k5_context,auth_context,&reply,&msg,&repdata))
  4982.               {
  4983.                 com_err("", r, "decoding tls verifier");
  4984.                 krb5_errno = r;
  4985.                 makestr(&krb5_errmsg,"TLS verify failure");
  4986.                 auth_finished(AUTH_REJECT);
  4987.                 return(AUTH_FAILURE);
  4988.             }
  4989.             if ( msg.length == 24 && !memcmp(msg.data,tls_verify,24) )
  4990.                  krb5_tls_verified = 1;
  4991.             krb5_free_data_contents(k5_context,&msg);
  4992.             if (krb5_tls_verified)
  4993.                 return(AUTH_SUCCESS);
  4994.         }
  4995.         printf("Man in the middle attack detected.  Session terminated.\r\n");
  4996.         netclos();
  4997.         krb5_errno = -1;
  4998.         makestr(&krb5_errmsg,"TLS verify failure");
  4999.         auth_finished(AUTH_REJECT);
  5000.         return(AUTH_FAILURE);
  5001. #endif /* CK_SSL */
  5002.  
  5003.     default:
  5004.         krb5_errno = -1;
  5005.         makestr(&krb5_errmsg,"Unknown reply type");
  5006.         auth_finished(AUTH_REJECT);
  5007.         return AUTH_FAILURE;                        /* Unknown reply type */
  5008.     }
  5009. }
  5010.  
  5011. #ifdef FORWARD
  5012. /* Decode, decrypt and store the forwarded creds in the local ccache. */
  5013. /* Needed for KRB5_FORWARD                                            */
  5014. static krb5_error_code
  5015. rd_and_store_for_creds(context, auth_context, inbuf, client)
  5016.     krb5_context context;
  5017.     krb5_auth_context auth_context;
  5018.     krb5_data *inbuf;
  5019.     krb5_const_principal client;
  5020. {
  5021.     krb5_creds ** creds=NULL;
  5022.     krb5_error_code retval;
  5023.     krb5_ccache ccache=NULL;
  5024.  
  5025. #ifdef HEIMDAL
  5026.     /*
  5027.     Heimdal Telnetd creates the cache file at this point and sets
  5028.     the KRB5CCNAME environment variable.
  5029.  
  5030.     struct passwd *pwd;
  5031.     char ccname[1024];
  5032.  
  5033.     pwd = getpwnam(szUserNameRequested);
  5034.     if (pwd == NULL)
  5035.         break;
  5036.     snprintf(ccname, sizeof(ccname)-1, "FILE:/tmp/krb5cc_%u",pwd->pw_uid);
  5037.     retval = krb5_cc_resolve(context,ccname,&ccache);
  5038.  
  5039.     chown(ccname + 5, pwd->pw_uid, -1);
  5040.     */
  5041. #endif /* HEIMDAL */
  5042.  
  5043.     if (retval = k5_get_ccache(context,&ccache,NULL))
  5044.         return(retval);
  5045.  
  5046. #ifdef HEIMDAL
  5047.     if ((retval = krb5_cc_initialize(context, ccache, client)))
  5048.         return(retval);
  5049.  
  5050.     if ((retval = krb5_rd_cred(context, auth_context, ccache, inbuf)))
  5051.         return(retval);
  5052. #else /* HEIMDAL */
  5053.     if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
  5054.         return(retval);
  5055.  
  5056.     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
  5057.         goto cleanup;
  5058.  
  5059.     if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
  5060.         goto cleanup;
  5061.  
  5062.     if ((retval = krb5_cc_close(context, ccache)))
  5063.         goto cleanup;
  5064.  
  5065.   cleanup:
  5066.     krb5_free_tgt_creds(context, creds);
  5067. #endif /* HEIMDAL */
  5068.     return retval;
  5069. }
  5070. #endif /* FORWARD */
  5071.  
  5072. /*
  5073.  *
  5074.  * K5_auth_is.
  5075.  *
  5076.  */
  5077.  
  5078. static int
  5079. #ifdef CK_ANSIC
  5080. k5_auth_is(int how, unsigned char *data, int cnt)
  5081. #else
  5082. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  5083. #endif
  5084. {
  5085.     int r = 0;
  5086.     krb5_principal server;
  5087.     krb5_keyblock *newkey = NULL;
  5088.     krb5_data outbuf;
  5089.     char errbuf[128]="";
  5090.     char *getenv();
  5091. #ifndef HEIMDAL
  5092.     krb5_authenticator *authenticator;
  5093.     krb5_keytab keytabid = 0;
  5094. #endif /* HEIMDAL */
  5095.     krb5_data inbuf;
  5096. #ifdef CK_ENCRYPTION
  5097.     Session_Key skey;
  5098. #endif /* CK_ENCRYPTION */
  5099.     char princ[256]="";
  5100.     int len;
  5101.  
  5102.     data += 4;                                  /* Point to status byte */
  5103.     cnt -= 4;
  5104.  
  5105.     hexdump("k5_auth_is data",data,cnt);
  5106.     debug(F111,"k5_auth_is","how",how);
  5107.  
  5108.     if (cnt-- < 1) {
  5109.         auth_finished(AUTH_REJECT);
  5110.         return AUTH_FAILURE;
  5111.     }
  5112.     switch (*data++) {
  5113.     case KRB_AUTH:
  5114.         k5_auth.data = (char *)data;
  5115.         k5_auth.length = cnt;
  5116.  
  5117.         debug(F110,"k5_auth_is","KRB_AUTH",0);
  5118.         debug(F111,"k5_auth_is","auth_context",auth_context);
  5119.  
  5120.         if (!r && !auth_context) {
  5121.             r = krb5_auth_con_init(k5_context, &auth_context);
  5122.             debug(F111,"k5_auth_is","krb5_auth_con_init",r);
  5123.         }
  5124.  
  5125. #ifdef HEIMDAL
  5126.         if (!r)
  5127.             r = krb5_auth_con_setaddrs_from_fd(k5_context,auth_context,&ttyfd);
  5128.  
  5129.         if (!r)
  5130.             r = krb5_sock_to_principal(k5_context,0,"host",
  5131.                                        KRB5_NT_SRV_HST,&server);
  5132.  
  5133.         if (!r)
  5134. #else /* HEIMDAL */
  5135.         if (!r) {
  5136.             krb5_rcache rcache = NULL;
  5137.  
  5138.             r = krb5_auth_con_getrcache(k5_context, auth_context,
  5139.                                          &rcache);
  5140.             debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
  5141.  
  5142.             if (!r && !rcache) {
  5143.                 /* Do not resolve server's principal name, we will check */
  5144.                 /* for validity after the krb5_rd_req() call.            */
  5145.                 r = krb5_sname_to_principal(k5_context, 0, 0,
  5146.                                              KRB5_NT_SRV_HST, &server);
  5147.                 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
  5148.  
  5149.                 if (!r) {
  5150.                     r = krb5_get_server_rcache(k5_context,
  5151.                         krb5_princ_component(k5_context, server, 0),
  5152.                                                 &rcache);
  5153.                     debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
  5154.                     krb5_free_principal(k5_context, server);
  5155.                 }
  5156.             }
  5157.             if (!r) {
  5158.                 r = krb5_auth_con_setrcache(k5_context,
  5159.                                              auth_context, rcache);
  5160.                 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
  5161.             }
  5162.         }
  5163.         if (!r && k5_keytab) {
  5164.             r = krb5_kt_resolve(k5_context,
  5165.                                  k5_keytab, &keytabid);
  5166.             debug(F111,"k5_auth_is","krb5_kt_resolve",r);
  5167.         }
  5168. #endif /* HEIMDAL */
  5169.         if (!r) {
  5170.             r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
  5171. #ifdef HEIMDAL
  5172.                              server, NULL, NULL,
  5173. #else /* HEIMDAL */
  5174.                              NULL, keytabid, NULL,
  5175. #endif /* HEIMDAL */
  5176.                              &k5_ticket);
  5177.             debug(F111,"k5_auth_is","krb5_rd_req",r);
  5178.         }
  5179.         if (r) {
  5180.             (void) ckstrncpy(errbuf, "krb5_rd_req failed: ",sizeof(errbuf));
  5181.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5182.             goto errout;
  5183.         }
  5184. #ifdef HEIMDAL
  5185.         krb5_free_principal(k5_context, server);
  5186.  
  5187.         {
  5188.             char type_check[26];
  5189.  
  5190.             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
  5191.             /* client and then server finished messages. */
  5192.  
  5193.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  5194.             type_check[1] = how;        /* not broken into parts */
  5195. #ifdef CK_SSL
  5196.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5197.                 ssl_get_client_finished(&type_check[2],12);
  5198.                 ssl_get_server_finished(&type_check[14],12);
  5199.                 hexdump("k5_auth_is type_check",type_check,26);
  5200.             }
  5201. #endif /* CK_SSL */
  5202.  
  5203.             r = krb5_verify_authenticator_checksum(k5_context,
  5204.                                                     auth_context,
  5205.                                                     type_check,
  5206. #ifdef CK_SSL
  5207.                 ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  5208. #endif /* CK_SSL */
  5209.                                                     2);
  5210.         }
  5211. #else /* HEIMDAL */
  5212.         len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
  5213.         if (len < 256)
  5214.         {
  5215.             memcpy(princ,
  5216.                    krb5_princ_component(k5_context,k5_ticket->server,0)->data,
  5217.                    len);
  5218.             princ[len] = '\0';
  5219.         }
  5220.         if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
  5221.         {
  5222.             debug(F110,"k5_auth_is incorrect service name",princ,0);
  5223.             ckstrncpy(errbuf,"incorrect service name: ",sizeof(errbuf));
  5224.             ckstrncat(errbuf,krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5225.                      sizeof(errbuf));
  5226.             ckstrncat(errbuf," != ",sizeof(errbuf));
  5227.             ckstrncat(errbuf,princ,sizeof(errbuf));
  5228.             goto errout;
  5229.         }
  5230.  
  5231.         r = krb5_auth_con_getauthenticator(k5_context,
  5232.                                             auth_context,
  5233.                                             &authenticator);
  5234.         debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
  5235.         if (r) {
  5236.             (void) ckstrncpy(errbuf,
  5237.                              "krb5_auth_con_getauthenticator failed: ",
  5238.                              sizeof(errbuf)
  5239.                              );
  5240.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5241.             goto errout;
  5242.         }
  5243.  
  5244.         if (authenticator->checksum) {
  5245.             char type_check[26];
  5246.             krb5_checksum *cksum = authenticator->checksum;
  5247.             krb5_keyblock *key;
  5248.  
  5249.             /* UPDATE for START_TLS. AUTH_ENCRYPT_START_TLS and inclusion of */
  5250.             /* client and then server finished messages. */
  5251.  
  5252.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  5253.             type_check[1] = how;        /* not broken into parts */
  5254. #ifdef CK_SSL
  5255.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5256.                 ssl_get_client_finished(&type_check[2],12);
  5257.                 ssl_get_server_finished(&type_check[14],12);
  5258.                 hexdump("k5_auth_is type_check",type_check,26);
  5259.             }
  5260. #endif /* CK_SSL */
  5261.  
  5262.             r = krb5_auth_con_getkey(k5_context, auth_context,
  5263.                                       &key);
  5264.             debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
  5265.             if (r) {
  5266.                 (void) ckstrncpy(errbuf, "krb5_auth_con_getkey failed: ",
  5267.                                   sizeof(errbuf));
  5268.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5269.                 goto errout;
  5270.             }
  5271.  
  5272.             r = krb5_verify_checksum(k5_context,
  5273.                                       cksum->checksum_type,
  5274.                                       cksum,
  5275.                                       &type_check,
  5276.                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  5277.                                       2,
  5278.                                       key->contents,
  5279.                                       key->length
  5280.                                       );
  5281.             debug(F111,"k5_auth_is","krb5_verify_checksum",r);
  5282.             if (r) {
  5283.                 (void) ckstrncpy(errbuf,
  5284.                                  "checksum verification failed: ",
  5285.                                  sizeof(errbuf)
  5286.                                  );
  5287.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5288.                 goto errout;
  5289.             }
  5290.             krb5_free_keyblock(k5_context, key);
  5291.         } else {
  5292.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
  5293.                 (void) strcpy(errbuf,
  5294.                                "authenticator is missing required checksum");
  5295.                 goto errout;
  5296.             }
  5297.         }
  5298.  
  5299.         krb5_free_authenticator(k5_context, authenticator);
  5300. #endif /* HEIMDAL */
  5301.  
  5302. #ifdef TLS_VERIFY
  5303.         if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  5304.             krb5_data in, msg;
  5305.             char tls_verify[24];
  5306.             krb5_replay_data repdata;
  5307.  
  5308.             ssl_get_server_finished(&tls_verify[0],12);
  5309.             ssl_get_client_finished(&tls_verify[12],12);
  5310.  
  5311.             in.data = tls_verify;
  5312.             in.length = 24;
  5313.  
  5314.             if (!krb5_d_no_addresses)
  5315.                 krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  5316.                                    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR);
  5317.             if (r = krb5_mk_safe(k5_context,auth_context,&in,&msg,&repdata)) {
  5318.                 com_err("", r, "encoding tls verifier");
  5319.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5320.                 goto errout;
  5321.             }
  5322.             SendK5AuthSB(KRB5_TLS_VERIFY, msg.data, msg.length);
  5323.             krb5_free_data_contents(k5_context,&msg);
  5324.         }
  5325. #endif /* CK_SSL */
  5326.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  5327.             /* do ap_rep stuff here */
  5328.             if ((r = krb5_mk_rep(k5_context,
  5329. #ifdef HEIMDAL
  5330.                                   &auth_context,
  5331. #else /* HEIMDAL */
  5332.                                   auth_context,
  5333. #endif /* HEIMDAL */
  5334.                                   &outbuf))) {
  5335.                 debug(F111,"k5_auth_is","krb5_mk_rep",r);
  5336.                 (void) ckstrncpy(errbuf, "Make reply failed: ",sizeof(errbuf));
  5337.                 (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5338.                 goto errout;
  5339.             }
  5340.             debug(F111,"k5_auth_is","krb5_mk_rep",r);
  5341.  
  5342.             SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
  5343.             mutual_complete = 1;
  5344.         }
  5345.  
  5346. #ifdef HEIMDAL
  5347.         {
  5348.             char * name = NULL;
  5349.             if (krb5_unparse_name(k5_context, k5_ticket->client,
  5350.                                    &name))
  5351.             {
  5352.                 szUserNameAuthenticated[0] = '\0';
  5353.             } else {
  5354.                 ckstrncpy(szUserNameAuthenticated,UIDBUFLEN,name);
  5355.                 free(name);
  5356.             }
  5357.         }
  5358. #else /* HEIMDAL */
  5359.         if ( krb5_aname_to_localname(k5_context,
  5360.                                       k5_ticket->enc_part2->client,
  5361.                                       UIDBUFLEN,szUserNameAuthenticated) )
  5362.             szUserNameAuthenticated[0] = '\0';
  5363. #endif /* HEIMDAL */
  5364.  
  5365.         SendK5AuthSB(KRB_ACCEPT, szUserNameAuthenticated,
  5366.                       szUserNameAuthenticated[0] ? -1 : 0);
  5367.         accept_complete = 1;
  5368.         ckmakmsg(strTmp,sizeof(strTmp),
  5369.                  "Kerberos5 identifies him as ``",
  5370.                  szUserNameAuthenticated,"''",NULL);
  5371.         printf("%s\r\n",strTmp);
  5372.  
  5373.         if (szUserNameRequested[0] &&
  5374.             krb5_kuserok(k5_context,
  5375. #ifdef HEIMDAL
  5376.                           k5_ticket->client,
  5377. #else /* HEIMDAL */
  5378.                           k5_ticket->enc_part2->client,
  5379. #endif /* HEIMDAL */
  5380.                           szUserNameRequested))
  5381.             auth_finished(AUTH_VALID);
  5382.         else
  5383.             auth_finished(AUTH_USER);
  5384.  
  5385.         krb5_auth_con_getremotesubkey(k5_context, auth_context,
  5386.                                        &newkey);
  5387.         if (k5_session_key) {
  5388.             krb5_free_keyblock(k5_context, k5_session_key);
  5389.             k5_session_key = 0;
  5390.         }
  5391.         if (newkey) {
  5392.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  5393.             krb5_free_keyblock(k5_context, newkey);
  5394.         } else {
  5395.             krb5_copy_keyblock(k5_context,
  5396. #ifdef HEIMDAL
  5397.                                 &k5_ticket->ticket.key,
  5398. #else /* HEIMDAL */
  5399.                                 k5_ticket->enc_part2->session,
  5400. #endif /* HEIMDAL */
  5401.                                 &k5_session_key);
  5402.         }
  5403.  
  5404. #ifdef CK_ENCRYPTION
  5405. #ifdef HEIMDAL
  5406.         skey.type = k5_session_key->keyvalue.length == 8 ? SK_DES : SK_GENERIC;
  5407.         skey.length = k5_session_key->keyvalue.length;
  5408.         skey.data = k5_session_key->keyvalue.data;
  5409. #else /* HEIMDAL */
  5410.         skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
  5411.         skey.length = k5_session_key->length;
  5412.         skey.data = k5_session_key->contents;
  5413. #endif /* HEIMDAL */
  5414.         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  5415. #endif /* CK_ENCRYPTION */
  5416.         debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
  5417.         krb5_errno = r;
  5418.         if ( krb5_errno )
  5419.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5420.         else
  5421.             makestr(&krb5_errmsg,strTmp);
  5422.         return AUTH_SUCCESS;
  5423.  
  5424. #ifdef FORWARD
  5425.     case KRB5_FORWARD:
  5426.         if ( !forward_flag ) {
  5427.             SendK5AuthSB(KRB5_FORWARD_REJECT,
  5428.                           "forwarded credentials are being refused.",
  5429.                           -1);
  5430.             return(AUTH_SUCCESS);
  5431.         }
  5432.  
  5433.         inbuf.length = cnt;
  5434.         inbuf.data = (char *)data;
  5435.         if (
  5436. #ifndef HEIMDAL
  5437.             (!krb5_d_no_addresses &&
  5438.             (r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
  5439.                               KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR))) ||
  5440. #endif /* HEIMDAL */
  5441.             (r = rd_and_store_for_creds(k5_context, auth_context,&inbuf,
  5442. #ifdef HEIMDAL
  5443.                                          k5_ticket->client
  5444. #else /* HEIMDAL */
  5445.                                          k5_ticket->enc_part2->client
  5446. #endif /* HEIMDAL */
  5447.                                          ))) {
  5448.             (void) ckstrncpy(errbuf, "Read forwarded creds failed: ",
  5449.                               sizeof(errbuf));
  5450.             (void) ckstrncat(errbuf, error_message(r),sizeof(errbuf));
  5451.             SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
  5452.             printf("Could not read forwarded credentials\r\n");
  5453.             krb5_errno = r;
  5454.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5455.         }
  5456.         else {
  5457.             SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
  5458.             ckstrncpy(strTmp,"Forwarded credentials obtained",sizeof(strTmp));
  5459.             printf("%s\r\n",strTmp);
  5460.             krb5_errno = 0;
  5461.             makestr(&krb5_errmsg,strTmp);
  5462.         }
  5463.         /* A failure to accept forwarded credentials is not an */
  5464.         /* authentication failure.                             */
  5465.         return AUTH_SUCCESS;
  5466. #endif  /* FORWARD */
  5467.     default:
  5468.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  5469.         SendK5AuthSB(KRB_REJECT, 0, 0);
  5470.         break;
  5471.     }
  5472.     auth_finished(AUTH_REJECT);
  5473.     return AUTH_FAILURE;
  5474.  
  5475.   errout:
  5476.     SendK5AuthSB(KRB_REJECT, errbuf, -1);
  5477.     krb5_errno = r;
  5478.     makestr(&krb5_errmsg,errbuf);
  5479.     printf("%s\r\n", errbuf);
  5480.     if (auth_context) {
  5481.         krb5_auth_con_free(k5_context, auth_context);
  5482.         auth_context = 0;
  5483.     }
  5484.     auth_finished(AUTH_REJECT);
  5485.     return AUTH_FAILURE;
  5486. }
  5487.  
  5488. #ifdef FORWARD
  5489. int
  5490. #ifdef CK_ANSIC
  5491. kerberos5_forward(void)
  5492. #else
  5493. kerberos5_forward()
  5494. #endif
  5495. {
  5496.     krb5_error_code r;
  5497.     krb5_ccache ccache=NULL;
  5498.     krb5_principal client = 0;
  5499.     krb5_principal server = 0;
  5500.     krb5_data forw_creds;
  5501. #ifdef HEIMDAL
  5502.     krb5_creds      creds;
  5503. #endif /* HEIMDAL */
  5504.  
  5505.     forw_creds.data = 0;
  5506.  
  5507.     r = k5_get_ccache(k5_context,&ccache,NULL);
  5508.     if ( r ) {
  5509.         com_err(NULL, r, "Kerberos V5: could not get default ccache");
  5510.         krb5_errno = r;
  5511.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5512.         return(AUTH_FAILURE);
  5513.     }
  5514.  
  5515.     if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
  5516.         com_err(NULL, r, "Kerberos V5: could not get default principal");
  5517.         goto cleanup;
  5518.     }
  5519.  
  5520. #ifdef HEIMDAL
  5521.     memset(&creds, 0, sizeof(creds));
  5522.     creds.client = client;
  5523.  
  5524.     if (r = krb5_build_principal(k5_context,
  5525.                              &creds.server,
  5526.                              strlen(client->realm),
  5527.                               client->realm,
  5528.                               "krbtgt",
  5529.                               client->realm,
  5530.                                   NULL)) {
  5531.         com_err(NULL, r, "Kerberos V5: could not get principal");
  5532.         goto cleanup;
  5533.     }
  5534.  
  5535.     creds.times.endtime = 0;
  5536.  
  5537.     if (r = krb5_get_forwarded_creds(k5_context,
  5538.                                       auth_context,
  5539.                                       ccache,
  5540.                                       0,
  5541.                                       szHostName,
  5542.                                       &creds,
  5543.                                       &forw_creds)) {
  5544.         com_err(NULL, r, "Kerberos V5: error getting forwarded creds");
  5545.         goto cleanup;
  5546.     }
  5547. #else /* HEIMDAL */
  5548.     /* we should not need to make this call since we are storing the */
  5549.     /* server's principal in fwd_server from our call to             */
  5550.     /* krb5_sname_to_principal() in k5_auth_send()                   */
  5551.     if (fwd_server == NULL) {
  5552.         if ((r = krb5_sname_to_principal(k5_context, szHostName,
  5553.                                  krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5554.                                           KRB5_NT_SRV_HST, &server))) {
  5555.             com_err(NULL, r, "Kerberos V5: could not make server principal");
  5556.             goto cleanup;
  5557.         }
  5558.     }
  5559.  
  5560.     if (!krb5_d_no_addresses &&
  5561.         (r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
  5562.                              KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR)))
  5563.     {
  5564.         com_err(NULL, r, "Kerberos V5: could not gen local full address");
  5565.         goto cleanup;
  5566.     }
  5567.  
  5568.     if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client,
  5569.                                 fwd_server ? fwd_server : server,
  5570.                                 ccache, forwardable_flag, &forw_creds)) {
  5571.         com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
  5572.         goto cleanup;
  5573.     }
  5574. #endif /* HEIMDAL */
  5575.  
  5576.     /* Send forwarded credentials */
  5577.     if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
  5578.         printf("Kerberos V5 forwarding error!\r\n%s\r\n",
  5579.                     "Not enough room for authentication data");
  5580.     }
  5581.  
  5582. cleanup:
  5583.     if (client)
  5584.         krb5_free_principal(k5_context, client);
  5585.     if (server)
  5586.         krb5_free_principal(k5_context, server);
  5587. #ifdef HEIMDAL
  5588.     krb5_data_free(&forw_creds);
  5589. #else /* HEIMDAL */
  5590.     krb5_free_data_contents(k5_context,&forw_creds);
  5591. #endif /* HEIMDAL */
  5592.     krb5_cc_close(k5_context, ccache);
  5593.  
  5594.     krb5_errno = r;
  5595.     makestr(&krb5_errmsg,krb5_errno?error_message(krb5_errno):"OK");
  5596.     return(r?AUTH_FAILURE:AUTH_SUCCESS);
  5597. }
  5598. #endif /* FORWARD */
  5599. #else /* KRB5 */
  5600. int
  5601. ck_krb5_autoget_TGT(char * dummy)
  5602. {
  5603.     return(0);
  5604. }
  5605. #ifdef CK_KERBEROS
  5606. int
  5607. #ifdef CK_ANSIC
  5608. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
  5609.                  struct krb4_init_data * k4_init)
  5610. #else
  5611. ck_krb5_initTGT(op,init,k4_init)
  5612.     krb_op_data * op; struct krb5_init_data * init;
  5613.     struct krb4_init_data * k4_init;
  5614. #endif /* CK_ANSIC*/
  5615. {
  5616.     return(-1);
  5617. }
  5618.  
  5619. int
  5620. #ifdef CK_ANSIC
  5621. ck_krb5_destroy(struct krb_op_data * op)
  5622. #else
  5623. ck_krb5_destroy(op) struct krb_op_data * op;
  5624. #endif
  5625. {
  5626.     return(-1);
  5627. }
  5628.  
  5629. int
  5630. #ifdef CK_ANSIC
  5631. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  5632. #else
  5633. ck_krb5_list_creds(op,lc)
  5634.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  5635. #endif
  5636. {
  5637.     return(-1);
  5638. }
  5639. #else /* CK_KERBEROS */
  5640. int
  5641. #ifdef CK_ANSIC
  5642. ck_krb5_initTGT(void * op, void * init, void * k4_init )
  5643. #else
  5644. ck_krb5_initTGT(op,init,k4_init)
  5645.     void * op; void * init; void * k4_init;
  5646. #endif /* CK_ANSIC*/
  5647. {
  5648.     return(-1);
  5649. }
  5650.  
  5651. int
  5652. #ifdef CK_ANSIC
  5653. ck_krb5_destroy(void * op)
  5654. #else
  5655. ck_krb5_destroy(op) void * op;
  5656. #endif
  5657. {
  5658.     return(-1);
  5659. }
  5660.  
  5661. int
  5662. #ifdef CK_ANSIC
  5663. ck_krb5_list_creds(void * op, void * lc)
  5664. #else
  5665. ck_krb5_list_creds(op,lc)
  5666.     void * op; void * lc;
  5667. #endif
  5668. {
  5669.     return(-1);
  5670. }
  5671. #endif /* CK_KERBEROS */
  5672. #endif /* KRB5 */
  5673.  
  5674. #ifdef GSSAPI_KRB5
  5675. /*
  5676.  *
  5677.  * gssk5_auth_send - gets authentication bits we need to send to KDC.
  5678.  *
  5679.  * Result is left in k5_auth
  5680.  *
  5681.  * Returns: 0 on failure, 1 on success
  5682.  *
  5683.  */
  5684.  
  5685. static int
  5686. #ifdef CK_ANSIC
  5687. gssk5_auth_send(int how, int encrypt, int forward)
  5688. #else
  5689. gssk5_auth_send(how,encrypt,forward) int how; int encrypt; int forward;
  5690. #endif
  5691. {
  5692.     OM_uint32 maj_stat, min_stat;
  5693. #ifdef KRB5
  5694.     char * realm = NULL;
  5695.     char tgt[256];
  5696. #endif /* KRB5 */
  5697.  
  5698.     gss_chan.initiator_addrtype = GSS_C_AF_INET; /* OM_uint32  */
  5699.     gss_chan.initiator_address.length = 4;
  5700.     gss_chan.initiator_address.value = &myctladdr.sin_addr.s_addr;
  5701.     gss_chan.acceptor_addrtype = GSS_C_AF_INET; /* OM_uint32 */
  5702.     gss_chan.acceptor_address.length = 4;
  5703.     gss_chan.acceptor_address.value = &hisctladdr.sin_addr.s_addr;
  5704.     gss_chan.application_data.length = 0;
  5705.     gss_chan.application_data.value = 0;
  5706.  
  5707. #ifdef KRB5
  5708.     realm = ck_krb5_realmofhost(ftp_host);
  5709.     if (realm) {
  5710.         ckmakmsg(tgt,sizeof(tgt),"krbtgt/",realm,"@",realm);
  5711.         debug(F110,"ftp_auth(GSSAPI) TGT",tgt,0);
  5712.         if ( krb5_autoget &&
  5713.              !((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  5714.                 (ck_krb5_is_tgt_valid() > 0)) )
  5715.             ck_krb5_autoget_TGT(realm);
  5716.     }
  5717. #endif /* KRB5 */
  5718.  
  5719.     /* Blob from gss-client */
  5720.     /* host@hostname */
  5721.     /* the V5 GSSAPI binding canonicalizes this for us... */
  5722.     ckmakmsg(gss_stbuf,GSS_BUFSIZ,
  5723.              krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  5724.              "@",
  5725.              szHostName,
  5726.               NULL
  5727.               );
  5728.     fprintf(stderr, "Authenticating to <%s>...\n", gss_stbuf);
  5729.     gss_send_tok.value = gss_stbuf;
  5730.     gss_send_tok.length = strlen(gss_stbuf);
  5731.     maj_stat = gss_import_name(&min_stat, &gss_send_tok,
  5732.                                 gss_nt_service_name,
  5733.                                 &gss_target_name
  5734.                                 );
  5735.     if (maj_stat != GSS_S_COMPLETE) {
  5736.         user_gss_error(maj_stat, min_stat, "parsing name");
  5737.         secure_error("name parsed <%s>\n", gss_stbuf);
  5738.         return(0);
  5739.     }
  5740.     token_ptr = GSS_C_NO_BUFFER;
  5741.     gcontext = GSS_C_NO_CONTEXT; /* structure copy */
  5742.  
  5743.     fprintf(stderr, "calling gss_init_sec_context\n");
  5744.     maj_stat =
  5745.         gss_init_sec_context(&min_stat,
  5746.                               GSS_C_NO_CREDENTIAL,
  5747.                               &gcontext,
  5748.                               gss_target_name,
  5749.                               gss_mech_krb5,
  5750.                               GSS_C_MUTUAL_FLAG |
  5751.                               GSS_C_REPLAY_FLAG |
  5752.                               ((forward && forward_flag) ?
  5753.                                 GSS_C_DELEG_FLAG : 0),
  5754.                               0,
  5755.                               (krb5_d_no_addresses ? /* channel bindings */
  5756.                                 GSS_C_NO_CHANNEL_BINDINGS :
  5757.                                 &gss_chan),
  5758.                               gss_token_ptr,
  5759.                               NULL,     /* ignore mech type */
  5760.                               &gss_send_tok,
  5761.                               NULL,     /* ignore ret_flags */
  5762.                               NULL
  5763.                               );        /* ignore time_rec */
  5764.  
  5765.  
  5766.         if (maj_stat != GSS_S_COMPLETE &&
  5767.              maj_stat != GSS_S_CONTINUE_NEEDED) {
  5768.             user_gss_error(maj_stat,
  5769.                             min_stat,
  5770.                             "initializing context"
  5771.                             );
  5772.             gss_release_name(&min_stat, &gss_target_name);
  5773.             return(0);
  5774.         }
  5775.         return(1);
  5776. }
  5777.  
  5778. /*
  5779.  * gssk5_auth_reply -- checks the reply for mutual authentication.
  5780.  */
  5781. static int
  5782. #ifdef CK_ANSIC
  5783. gssk5_auth_reply(int how, unsigned char *data, int cnt)
  5784. #else
  5785. gssk5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  5786. #endif
  5787. {
  5788.     data += 4;                                  /* Point to status byte */
  5789.     cnt -=5;
  5790.  
  5791.     switch (*data++) {
  5792.     case GSS_REJECT:
  5793.         if (cnt > 0) {
  5794.             char *s;
  5795.             int len;
  5796.             ckstrncpy(strTmp,"GSSAPI refuses authentication because\r\n",
  5797.                       sizeof(strTmp));
  5798.             len = strlen(strTmp);
  5799.             if ( len + cnt < sizeof(strTmp) ) {
  5800.                 s = strTmp + strlen(strTmp);
  5801.                 memcpy(s, data, cnt);           /* safe */
  5802.                 s[cnt] = 0;
  5803.             }
  5804.         } else
  5805.             ckstrncpy(strTmp,"GSSAPI refuses authentication",
  5806.                       sizeof(strTmp));
  5807.         printf("GSSAPI authentication failed!\r\n%s\r\n",strTmp);
  5808.         auth_finished(AUTH_REJECT);
  5809.         return AUTH_FAILURE;
  5810.  
  5811.     case GSS_ACCEPT:
  5812.         if ( cnt > 0 ) {
  5813.             char *s;
  5814.             int len;
  5815.             ckstrncpy(strTmp,"GSSAPI accepts you as ",sizeof(strTmp));
  5816.             len = strlen(strTmp);
  5817.             if ( len + cnt < sizeof(strTmp) ) {
  5818.                 s = strTmp + strlen(strTmp);
  5819.                 memcpy(s,data,cnt);
  5820.                 s[cnt] = 0;
  5821.             }
  5822.         }
  5823.         accept_complete = 1;
  5824.         printf("%s\r\n",strTmp);
  5825.         auth_finished(AUTH_USER);
  5826.         return AUTH_SUCCESS;
  5827.  
  5828.     case GSS_RESPONSE:
  5829.         gss_token_ptr = &gss_recv_tok;
  5830.         gss_recv_tok.value = data;
  5831.         gss_recv_tok.length = cnt;
  5832.  
  5833.         maj_stat =
  5834.             gss_init_sec_context(&min_stat,
  5835.                                   GSS_C_NO_CREDENTIAL,
  5836.                                   &gcontext,
  5837.                                   gss_target_name,
  5838.                                   gss_krb5_mech,
  5839.                                   GSS_C_MUTUAL_FLAG |
  5840.                                   GSS_C_REPLAY_FLAG |
  5841.                                   (forward_flag ?
  5842.                                     GSS_C_DELEG_FLAG : 0),
  5843.                                   0,
  5844.                                   (krb5_d_no_addresses ? /* channel bindings */
  5845.                                     GSS_C_NO_CHANNEL_BINDINGS :
  5846.                                     &gss_chan),
  5847.                                   gss_token_ptr,
  5848.                                   NULL, /* ignore mech type */
  5849.                                   &gss_send_tok,
  5850.                                   NULL, /* ignore ret_flags */
  5851.                                   NULL
  5852.                                   );    /* ignore time_rec */
  5853.  
  5854.         if ( maj_stat == GSS_S_COMPLETE )
  5855.         {
  5856.  
  5857.         } else if ( maj_stat == CSS_S_CONTINUE_NEEDED ) {
  5858.         } else {
  5859.         }
  5860.  
  5861.         ckstrncpy(strTmp,"Remote machine has been mutually authenticated",
  5862.                   sizeof(strTmp));
  5863.         printf("%s\r\n",strTmp);
  5864.         auth_finished(AUTH_USER);
  5865.         return AUTH_SUCCESS;
  5866.  
  5867.     default:
  5868.         auth_finished(AUTH_REJECT);
  5869.         return AUTH_FAILURE;                        /* Unknown reply type */
  5870.     }
  5871. }
  5872.  
  5873. /*
  5874.  *
  5875.  * gssk5_auth_is.
  5876.  *
  5877.  */
  5878.  
  5879. static int
  5880. #ifdef CK_ANSIC
  5881. k5_auth_is(int how, unsigned char *data, int cnt)
  5882. #else
  5883. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  5884. #endif
  5885. {
  5886.     int replied = 0;
  5887.     gss_cred_id_t server_creds, deleg_creds;
  5888.     gss_name_t client;
  5889.     int ret_flags;
  5890.     gss_buffer_desc name_buf;
  5891.     gss_name_t server_name;
  5892.     OM_uint32 acquire_maj,
  5893.       acquire_min,
  5894.       accept_maj,
  5895.       accept_min,
  5896.       stat_maj,
  5897.       stat_min;
  5898.     gss_OID mechid;
  5899.     gss_buffer_desc tok, out_tok;
  5900.     char gbuf[GSS_BUFSIZ];
  5901.     u_char gout_buf[GSS_BUFSIZ];
  5902.     char localname[MAXHOSTNAMELEN];
  5903.     char service_name[MAXHOSTNAMELEN+10];
  5904.     char **service;
  5905.     struct hostent *hp;
  5906.  
  5907.     data += 4;                                  /* Point to status byte */
  5908.     cnt -= 4;
  5909.  
  5910.     hexdump("gssk5_auth_is data",data,cnt);
  5911.     debug(F111,"gssk5_auth_is","how",how);
  5912.  
  5913.     if (cnt-- < 1) {
  5914.         auth_finished(AUTH_REJECT);
  5915.         return AUTH_FAILURE;
  5916.     }
  5917.     switch (*data++) {
  5918.     case GSS_AUTH:
  5919.         gss_chan.initiator_addrtype = GSS_C_AF_INET;
  5920.         gss_chan.initiator_address.length = 4;
  5921.         gss_chan.initiator_address.value = &his_addr.sin_addr.s_addr;
  5922.         gss_chan.acceptor_addrtype = GSS_C_AF_INET;
  5923.         gss_chan.acceptor_address.length = 4;
  5924.         gss_chan.acceptor_address.value = &ctrl_addr.sin_addr.s_addr;
  5925.         gss_chan.application_data.length = 0;
  5926.         gss_chan.application_data.value = 0;
  5927.  
  5928.         tok.value = data;
  5929.         tok.length = cnt;
  5930.  
  5931.         if (gethostname(localname, MAXHOSTNAMELEN)) {
  5932.             auth_finished(AUTH_REJECT);
  5933.             return AUTH_FAILURE;
  5934.         }
  5935.         if (!(hp = gethostbyname(localname))) {
  5936.             auth_finished(AUTH_REJECT);
  5937.             return AUTH_FAILURE;
  5938.         }
  5939. #ifdef HADDRLIST
  5940.         hp = ck_copyhostent(hp);
  5941. #endif /* HADDRLIST */
  5942.         strncpy(localname, hp->h_name, sizeof(localname) - 1);
  5943.         localname[sizeof(localname) - 1] = '\0';
  5944.  
  5945.         sprintf(service_name, "%s@%s", *service, localname);
  5946.         name_buf.value = service_name;
  5947.         name_buf.length = strlen(name_buf.value) + 1;
  5948.         stat_maj = gss_import_name(&stat_min, &name_buf,
  5949.                                     gss_nt_service_name,
  5950.                                     &server_name);
  5951.         if (stat_maj != GSS_S_COMPLETE) {
  5952.             auth_finished(AUTH_REJECT);
  5953.             return AUTH_FAILURE;
  5954.         }
  5955.  
  5956.         acquire_maj = gss_acquire_cred(&acquire_min, server_name, 0,
  5957.                                         GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
  5958.                                         &server_creds, NULL, NULL);
  5959.         (void) gss_release_name(&stat_min, &server_name);
  5960.  
  5961.         if (acquire_maj != GSS_S_COMPLETE) {
  5962.             reply_gss_error(535, accept_maj, accept_min,
  5963.                                  "accepting context");
  5964.             syslog(LOG_ERR, "failed accepting context");
  5965.             (void) gss_release_cred(&stat_min, &server_creds);
  5966.             if (ret_flags & GSS_C_DELEG_FLAG)
  5967.                 (void) gss_release_cred(&stat_min,
  5968.                                          &deleg_creds);
  5969.             return 0;
  5970.         }
  5971.  
  5972.         gcontext = GSS_C_NO_CONTEXT;
  5973.         accept_maj = gss_accept_sec_context(&accept_min,
  5974.                                             &gcontext, /* context_handle */
  5975.                                             /* verifier_cred_handle */
  5976.                                             server_creds,
  5977.                                             &tok, /* input_token */
  5978.                                              (krb5_d_no_addresses ? /* channel bindings */
  5979.                                                GSS_C_NO_CHANNEL_BINDINGS :
  5980.                                                &gss_chan),
  5981.                                              &client, /* src_name */
  5982.                                             &mechid, /* mech_type */
  5983.                                             &out_tok, /* output_token */
  5984.                                             &ret_flags,
  5985.                                             NULL,       /* ignore time_rec */
  5986.                                             /* forwarded credentials */
  5987.                                             &deleg_creds
  5988.                                             );
  5989.  
  5990.         if (accept_maj!=GSS_S_COMPLETE && accept_maj!=GSS_S_CONTINUE_NEEDED) {
  5991.             reply_gss_error(535, accept_maj, accept_min,
  5992.                              "accepting context");
  5993.             syslog(LOG_ERR, "failed accepting context");
  5994.             (void) gss_release_cred(&stat_min, &server_creds);
  5995.             if (ret_flags & GSS_C_DELEG_FLAG)
  5996.                 (void) gss_release_cred(&stat_min,
  5997.                                          &deleg_creds);
  5998.             return 0;
  5999.         }
  6000.  
  6001.         if (out_tok.length) {
  6002.             if (kerror = radix_encode(out_tok.value,gbuf,&out_tok.length, 0)) {
  6003.                 secure_error("Couldn't encode ADAT reply (%s)",
  6004.                              radix_error(kerror));
  6005.                 syslog(LOG_ERR, "couldn't encode ADAT reply");
  6006.                 (void) gss_release_cred(&stat_min, &server_creds);
  6007.                 if (ret_flags & GSS_C_DELEG_FLAG)
  6008.                         (void) gss_release_cred(&stat_min,
  6009.                                                 &deleg_creds);
  6010.                 return(0);
  6011.             }
  6012.             if (stat_maj == GSS_S_COMPLETE) {
  6013.                 reply(235, "ADAT=%s", gbuf);
  6014.                 replied = 1;
  6015.             } else {
  6016.                 /* If the server accepts the security data, and
  6017.                    requires additional data, it should respond
  6018.                    with reply code 335. */
  6019.                 reply(335, "ADAT=%s", gbuf);
  6020.             }
  6021.             (void) gss_release_buffer(&stat_min, &out_tok);
  6022.         }
  6023.  
  6024.         if (stat_maj == GSS_S_COMPLETE) {
  6025.             /* GSSAPI authentication succeeded */
  6026.             stat_maj = gss_display_name(&stat_min, client,
  6027.                                          &client_name, &mechid);
  6028.             if (stat_maj != GSS_S_COMPLETE) {
  6029.                 /* "If the server rejects the security data (if
  6030.                    a checksum fails, for instance), it should
  6031.                    respond with reply code 535." */
  6032.                 reply_gss_error(535, stat_maj, stat_min,
  6033.                                 "extracting GSSAPI identity name");
  6034.                 syslog(LOG_ERR, "gssapi error extracting identity");
  6035.                 (void) gss_release_cred(&stat_min, &server_creds);
  6036.                 if (ret_flags & GSS_C_DELEG_FLAG)
  6037.                         (void) gss_release_cred(&stat_min,
  6038.                                                 &deleg_creds);
  6039.                 return 0;
  6040.             }
  6041.             auth_type = temp_auth_type;
  6042.             temp_auth_type = NULL;
  6043.  
  6044.             (void) gss_release_cred(&stat_min, &server_creds);
  6045.             if (ret_flags & GSS_C_DELEG_FLAG) {
  6046.                 if (want_creds)
  6047.                     ftpd_gss_convert_creds(client_name.value,
  6048.                                             deleg_creds);
  6049.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6050.             }
  6051.  
  6052.             /* If the server accepts the security data, but does
  6053.                not require any additional data (i.e., the security
  6054.                data exchange has completed successfully), it must
  6055.                respond with reply code 235. */
  6056.             if (!replied)
  6057.             {
  6058.                 if (ret_flags & GSS_C_DELEG_FLAG && !have_creds)
  6059.                   reply(235,
  6060.  "GSSAPI Authentication succeeded, but could not accept forwarded credentials"
  6061.                         );
  6062.                 else
  6063.                   reply(235, "GSSAPI Authentication succeeded");
  6064.             }
  6065.             return(1);
  6066.         } else if (stat_maj == GSS_S_CONTINUE_NEEDED) {
  6067.             /* If the server accepts the security data, and
  6068.             requires additional data, it should respond with
  6069.             reply code 335. */
  6070.             reply(335, "more data needed");
  6071.             (void) gss_release_cred(&stat_min, &server_creds);
  6072.             if (ret_flags & GSS_C_DELEG_FLAG)
  6073.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6074.             return(0);
  6075.         } else {
  6076.             /* "If the server rejects the security data (if
  6077.             a checksum fails, for instance), it should
  6078.             respond with reply code 535." */
  6079.             reply_gss_error(535, stat_maj, stat_min,
  6080.                              "GSSAPI failed processing ADAT");
  6081.             syslog(LOG_ERR, "GSSAPI failed processing ADAT");
  6082.             (void) gss_release_cred(&stat_min, &server_creds);
  6083.             if (ret_flags & GSS_C_DELEG_FLAG)
  6084.                 (void) gss_release_cred(&stat_min, &deleg_creds);
  6085.             return(0);
  6086.         }
  6087.  
  6088.         debug(F100,"gssk5_auth_is AUTH_SUCCESS","",0);
  6089.         krb5_errno = r;
  6090.         if ( krb5_errno )
  6091.             makestr(&krb5_errmsg,error_message(krb5_errno));
  6092.         else
  6093.             makestr(&krb5_errmsg,strTmp);
  6094.         return AUTH_SUCCESS;
  6095.  
  6096.     default:
  6097.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  6098.         SendGSSK5AuthSB(GSS_REJECT, 0, 0);
  6099.         break;
  6100.     }
  6101.     auth_finished(AUTH_REJECT);
  6102.     return AUTH_FAILURE;
  6103. }
  6104. #endif /* GSSAPI_KRB5 */
  6105.  
  6106. #ifdef CK_SRP
  6107. /*
  6108.  * Copyright (c) 1997 Stanford University
  6109.  *
  6110.  * The use of this software for revenue-generating purposes may require a
  6111.  * license from the owners of the underlying intellectual property.
  6112.  * Specifically, the SRP-3 protocol may not be used for revenue-generating
  6113.  * purposes without a license.
  6114.  *
  6115.  * NOTE: Columbia University has a license.
  6116.  *
  6117.  * Within that constraint, permission to use, copy, modify, and distribute
  6118.  * this software and its documentation for any purpose is hereby granted
  6119.  * without fee, provided that the above copyright notices and this permission
  6120.  * notice appear in all copies of the software and related documentation.
  6121.  *
  6122.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  6123.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  6124.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  6125.  *
  6126.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  6127.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  6128.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
  6129.  * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
  6130.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  6131.  */
  6132.  
  6133. static void
  6134. srp_encode_length(data, num)
  6135.     unsigned char * data;
  6136.     int num;
  6137. {
  6138.     *data = (num >> 8) & 0xff;
  6139.     *++data = num & 0xff;
  6140. }
  6141.  
  6142. static int
  6143. srp_decode_length(data)
  6144.     unsigned char * data;
  6145. {
  6146.     return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
  6147. }
  6148.  
  6149. #ifdef PRE_SRP_1_7_3
  6150. static int
  6151. #ifdef CK_ANSIC
  6152. srp_reply(int how, unsigned char *data, int cnt)
  6153. #else
  6154. srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  6155. #endif
  6156. {
  6157.     struct t_num n;
  6158.     struct t_num g;
  6159.     struct t_num s;
  6160.     struct t_num B;
  6161.     struct t_num * A;
  6162.     char hexbuf[MAXHEXPARAMLEN];
  6163.     char type_check[26];
  6164.     int pflag;
  6165.  
  6166. #ifdef CK_ENCRYPTION
  6167.     Session_Key skey;
  6168. #endif /* ENCRYPTION */
  6169.  
  6170.     char * str=NULL;
  6171.  
  6172.     data += 4;                          /* Point to status byte */
  6173.     cnt  -= 4;
  6174.  
  6175.     if(cnt-- < 1) {
  6176.         auth_finished(AUTH_REJECT);
  6177.         return AUTH_FAILURE;
  6178.     }
  6179.  
  6180.     switch(*data++) {
  6181.     case SRP_REJECT:
  6182.         ckmakmsg(strTmp,sizeof(strTmp),
  6183.                   "SRP refuses authentication for '",szUserName,
  6184.                   "'\r\n",NULL);
  6185.         if (cnt > 0) {
  6186.             int len = strlen(strTmp);
  6187.             if ( len + cnt < sizeof(strTmp) ) {
  6188.                 str = strTmp + strlen(strTmp);
  6189.                 memcpy(str,data,cnt);
  6190.                 str[cnt] = 0;
  6191.             }
  6192.         }
  6193.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  6194.         if (tc != NULL) {
  6195.             t_clientclose(tc);
  6196.             tc = NULL;
  6197.         }
  6198.         auth_finished(AUTH_REJECT);
  6199.         return AUTH_FAILURE;
  6200.  
  6201.     case SRP_ACCEPT:
  6202.         if(cnt < RESPONSE_LEN || !srp_waitresp ||
  6203.             tc == NULL
  6204.             ) {
  6205.             printf("SRP Protocol error\r\n");
  6206.             return(auth_resend(AUTHTYPE_SRP));
  6207.         }
  6208.         srp_waitresp = 0;
  6209.  
  6210.         if(t_clientverify(tc, data) == 0) {
  6211.             printf("SRP accepts you as %s\r\n",szUserName);
  6212. #ifdef CK_SSL
  6213.             if((ssl_active_flag || tls_active_flag) &&
  6214.                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6215.                 printf("TLS session parameters verified by SRP\r\n");
  6216.             } else
  6217. #endif /* CK_SSL */
  6218.  
  6219. #ifdef CK_ENCRYPTION
  6220.             {
  6221.                 skey.type = SK_GENERIC;
  6222.                 skey.length = SESSION_KEY_LEN;
  6223.                 skey.data = tc->session_key;
  6224.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  6225.             }
  6226. #endif /* ENCRYPTION */
  6227.             t_clientclose(tc);
  6228.             tc = NULL;
  6229.             accept_complete = 1;
  6230.             auth_finished(AUTH_VALID);
  6231.             return AUTH_SUCCESS;
  6232.         } else {
  6233.             printf("SRP server authentication failed!\r\n");
  6234.             t_clientclose(tc);
  6235.             tc = NULL;
  6236.             return(auth_resend(AUTHTYPE_SRP));
  6237.         }
  6238.         break;
  6239.  
  6240.     case SRP_PARAMS:
  6241.         if(!szUserName) {
  6242.             printf("No username available\r\n");
  6243.             return(auth_resend(AUTHTYPE_SRP));
  6244.         }
  6245.  
  6246.         n.len = srp_decode_length(data);
  6247.         data += 2;
  6248.         cnt -= 2;
  6249.         if(n.len > cnt) {
  6250.             printf("n too long\r\n");
  6251.             return(auth_resend(AUTHTYPE_SRP));
  6252.         }
  6253.         n.data = data;
  6254.         data += n.len;
  6255.         cnt -= n.len;
  6256.  
  6257.         g.len = srp_decode_length(data);
  6258.         data += 2;
  6259.         cnt -= 2;
  6260.         if(g.len > cnt) {
  6261.             printf("g too long\r\n");
  6262.             return(auth_resend(AUTHTYPE_SRP));
  6263.         }
  6264.         g.data = data;
  6265.         data += g.len;
  6266.         cnt -= g.len;
  6267.  
  6268.         s.len = srp_decode_length(data);
  6269.         data += 2;
  6270.         cnt -= 2;
  6271.         if(s.len > cnt) {
  6272.             printf("salt too long\r\n");
  6273.             return(auth_resend(AUTHTYPE_SRP));
  6274.         }
  6275.         s.data = data;
  6276.         data += s.len;
  6277.         cnt -= s.len;
  6278.  
  6279.         /* If the parameters provided by the server cannot be
  6280.          * validated the following function will fail.
  6281.          */
  6282.         tc = t_clientopen(szUserName, &n, &g, &s);
  6283.         if (tc == NULL) {
  6284.             printf("SRP parameter initialization error\r\n");
  6285.             return(auth_resend(AUTHTYPE_SRP));
  6286.         }
  6287.         A = t_clientgenexp(tc);
  6288.         if(A == NULL) {
  6289.             printf("SRP protocol error\r\n");
  6290.             return(auth_resend(AUTHTYPE_SRP));
  6291.         }
  6292.         SendSRPAuthSB(SRP_EXP, A->data, A->len);
  6293.  
  6294.         if ( pwbuf[0] && pwflg ) {
  6295.             printf("SRP using %d-bit modulus for '%s'\r\n",
  6296.                    8 * n.len,
  6297.                    szUserName
  6298.                    );
  6299.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  6300. #ifdef OS2
  6301.             if ( pwcrypt )
  6302.                 ck_encrypt((char *)srp_passwd);
  6303. #endif /* OS2 */
  6304.         } else {
  6305.             extern char * srppwprompt;
  6306.             char prompt[128];
  6307.  
  6308.             if (srppwprompt && srppwprompt[0] &&
  6309.                (strlen(srppwprompt) + strlen(szUserName) - 2) < sizeof(prompt))
  6310.             {
  6311.                 sprintf(prompt,srppwprompt,szUserName);
  6312.             } else {
  6313.                 ckmakxmsg( prompt,sizeof(prompt),
  6314.                            "SRP using ",ckitoa(8*n.len),"-bit modulus\r\n",
  6315.                            szUserName,"'s password: ",
  6316.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6317.             }
  6318.             readpass(prompt,srp_passwd,sizeof(srp_passwd)-1);
  6319.         }
  6320.  
  6321.         t_clientpasswd(tc, srp_passwd);
  6322.         memset(srp_passwd, 0, sizeof(srp_passwd));
  6323.         return AUTH_SUCCESS;
  6324.  
  6325.     case SRP_CHALLENGE:
  6326.         if(tc == NULL) {
  6327.             printf("SRP protocol error\r\n");
  6328.             return(auth_resend(AUTHTYPE_SRP));
  6329.         }
  6330.  
  6331. #ifndef PRE_SRP_1_4_5
  6332.         /*
  6333.          * The original SRP AUTH implementation did not protect against
  6334.          * tampering of the auth-type-pairs.  Therefore, when the
  6335.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6336.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6337.          * is set we also insert the SSL/TLS client and server finished
  6338.          * messages to ensure that there is no man in the middle attack
  6339.          * underway on the SSL/TLS connection.
  6340.          */
  6341.         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
  6342.             type_check[0] = AUTHTYPE_SRP;
  6343.             type_check[1] = how;
  6344. #ifdef CK_SSL
  6345.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6346.                 ssl_get_client_finished(&type_check[2],12);
  6347.                 ssl_get_server_finished(&type_check[14],12);
  6348.                 t_clientaddexdata(tc,type_check,26);
  6349.             } else
  6350. #endif /* CK_SSL */
  6351.                 t_clientaddexdata(tc,type_check,2);
  6352.         }
  6353. #endif /* PRE_SRP_1_4_5 */
  6354.  
  6355.         B.data = data;
  6356.         B.len = cnt;
  6357.         t_clientgetkey(tc, &B);
  6358.  
  6359.         SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
  6360.         srp_waitresp = 1;
  6361.         return AUTH_SUCCESS;
  6362.  
  6363.     default:
  6364.         return(auth_resend(AUTHTYPE_SRP));
  6365.     }
  6366.     return AUTH_FAILURE;
  6367. }
  6368.  
  6369. static int
  6370. #ifdef CK_ANSIC
  6371. srp_is(int how, unsigned char *data, int cnt)
  6372. #else
  6373. srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  6374. #endif
  6375. {
  6376.     char pbuf[2 * MAXPARAMLEN + 5];
  6377.     char * ptr;
  6378.     char hexbuf[MAXHEXPARAMLEN];
  6379. #ifdef CK_ENCRYPTION
  6380.     Session_Key skey;
  6381. #endif
  6382.     struct t_num A;
  6383.     struct t_pw * tpw = NULL;
  6384.     struct t_conf * tconf = NULL;
  6385.     struct passwd * pass;
  6386.     static struct t_num * B = NULL;     /* Holder for B */
  6387. #ifdef CK_SSL
  6388.     char type_check[26];
  6389. #else
  6390.     char type_check[2];
  6391. #endif /* CK_SSL */
  6392.  
  6393.     if ((cnt -= 4) < 1) {
  6394.         auth_finished(AUTH_REJECT);
  6395.         return AUTH_FAILURE;
  6396.     }
  6397.  
  6398.     data += 4;
  6399.     cnt  -= 1;
  6400.     switch(*data++) {
  6401.     case SRP_AUTH:
  6402.         /* Send parameters back to client */
  6403.         if(ts != NULL) {
  6404.             t_serverclose(ts);
  6405.             ts = NULL;
  6406.         }
  6407.         if(!szUserNameRequested[0]) {
  6408.             if (1)
  6409.                 printf("No username available\r\n");
  6410.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  6411.             auth_finished(AUTH_REJECT);
  6412.             return(AUTH_FAILURE);
  6413.         }
  6414. #ifdef IKSD
  6415. #ifdef CK_LOGIN
  6416.         if (inserver && ckxanon &&
  6417.              !strcmp(szUserNameRequested,"anonymous")) {
  6418.             SendSRPAuthSB(SRP_REJECT, (void *)
  6419.             "anonymous login cannot be performed with Secure Remote Password",
  6420.             -1);
  6421.             auth_finished(AUTH_REJECT);
  6422.             return(AUTH_FAILURE);
  6423.         }
  6424. #endif /* CK_LOGIN */
  6425. #endif /* IKSD */
  6426. #ifndef PRE_SRP_1_4_4
  6427.         if(tpw == NULL) {
  6428.             if((tpw = t_openpw(NULL)) == NULL) {
  6429.                 if (1)
  6430.                     printf("Unable to open password file\r\n");
  6431.                 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
  6432.                 return(AUTH_FAILURE);
  6433.             }
  6434.         }
  6435.         if(tconf == NULL) {
  6436.             if((tconf = t_openconf(NULL)) == NULL) {
  6437.                 if (1)
  6438.                   printf("Unable to open configuration file\r\n");
  6439.                 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
  6440.                 return(AUTH_FAILURE);
  6441.             }
  6442.         }
  6443.         ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  6444.         t_closepw(tpw);
  6445.         tpw = NULL;
  6446.         t_closeconf(tconf);
  6447.         tconf = NULL;
  6448. #else /* PRE_SRP_1_4_4 */
  6449. #ifdef COMMENT
  6450.         /* the code in this block should no longer be necessary on OS/2
  6451.            or Windows because I have added functionality to libsrp.lib
  6452.            to find the srp files.   4/22/2000
  6453.         */
  6454.  
  6455.         /* On Windows and OS/2 there is no well defined place for the */
  6456.         /* ETC directory.  So we look for either an SRP_ETC or ETC    */
  6457.         /* environment variable in that order.  If we find one we     */
  6458.         /* attempt to open the files manually.                        */
  6459.         /* We will reuse the pbuf[] for the file names. */
  6460.         ptr = getenv("SRP_ETC");
  6461.         if ( !ptr )
  6462.             ptr = getenv("ETC");
  6463. #ifdef NT
  6464.         if ( !ptr ) {
  6465.             DWORD len;
  6466.             len = (2 * MAXPARAMLEN + 5);
  6467.  
  6468.             len = GetWindowsDirectory(pbuf,len);
  6469.             if ( len > 0 && len < (2 * MAXPARAMLEN + 5)) {
  6470.                 if ( !isWin95() ) {
  6471.                     if ( len == 1 )
  6472.                         ckstrncat(pbuf,"SYSTEM32/DRIVERS/ETC",sizeof(pbuf));
  6473.                     else
  6474.                         ckstrncat(pbuf,"/SYSTEM32/DRIVERS/ETC",sizeof(pbuf));
  6475.                 }
  6476.             }
  6477.             ptr = pbuf;
  6478.         }
  6479. #endif /* NT */
  6480.         if ( ptr ) {
  6481.             int len = strlen(ptr);
  6482.             int i;
  6483.             strcpy(pbuf,ptr);
  6484.             for ( i=0;i<len;i++ ) {
  6485.                 if ( pbuf[i] == '\\' )
  6486.                     pbuf[i] = '/';
  6487.             }
  6488.             if ( pbuf[len-1] != '/' )
  6489.                 ckstrncat(pbuf,"/tpasswd",sizeof(pbuf));
  6490.             else
  6491.                 ckstrncat(pbuf,"tpasswd",sizeof(pbuf));
  6492.             tpw = t_openpwbyname(pbuf);
  6493.  
  6494.             ckstrncat(pbuf,".conf",sizeof(pbuf));
  6495.             tconf = t_openconfbyname(pbuf);
  6496.         }
  6497.  
  6498.         if ( tpw && tconf )
  6499.             ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  6500.         else
  6501.             ts = t_serveropen(szUserNameRequested);
  6502.         if ( tpw ) {
  6503.             t_closepw(tpw);
  6504.             tpw = NULL;
  6505.         }
  6506.         if ( tconf ) {
  6507.             t_closeconf(tconf);
  6508.             tconf = NULL;
  6509.         }
  6510. #else /* COMMENT */
  6511.         ts = t_serveropen(szUserNameRequested);
  6512. #endif /* COMMENT */
  6513. #endif /* PRE_SRP_1_4_4 */
  6514.  
  6515.         if( ts == NULL ) {
  6516.             printf("User %s not found\r\n", szUserNameRequested);
  6517.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  6518.             return(AUTH_FAILURE);
  6519.         }
  6520.  
  6521.         if ( ts->n.len + ts->g.len + ts->s.len + 6 > sizeof(pbuf) ) {
  6522.             printf("message length error\r\n");
  6523.             SendSRPAuthSB(SRP_REJECT, (void *) "message length error", -1);
  6524.             return(AUTH_FAILURE);
  6525.         }
  6526.         ptr = pbuf;
  6527.  
  6528.         srp_encode_length(ptr, ts->n.len);
  6529.         ptr += 2;
  6530.         memcpy(ptr, ts->n.data, ts->n.len);     /* safe */
  6531.         ptr += ts->n.len;
  6532.  
  6533.         srp_encode_length(ptr, ts->g.len);
  6534.         ptr += 2;
  6535.         memcpy(ptr, ts->g.data, ts->g.len);     /* safe */
  6536.         ptr += ts->g.len;
  6537.  
  6538.         srp_encode_length(ptr, ts->s.len);
  6539.         ptr += 2;
  6540.         memcpy(ptr, ts->s.data, ts->s.len);     /* safe */
  6541.         ptr += ts->s.len;
  6542.  
  6543.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  6544.  
  6545.         B = t_servergenexp(ts);
  6546.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
  6547.         return AUTH_SUCCESS;
  6548.  
  6549.     case SRP_EXP:
  6550.         /* Client is sending A to us, compute challenge & expected response. */
  6551.         if (ts == NULL || B == NULL) {
  6552.             printf("Protocol error: SRP_EXP unexpected\r\n");
  6553.             SendSRPAuthSB(SRP_REJECT,
  6554.                           (void *) "Protocol error: unexpected EXP",
  6555.                           -1
  6556.                           );
  6557.             return(AUTH_FAILURE);
  6558.         }
  6559.  
  6560.         /* Wait until now to send B, since it contains the key to "u" */
  6561.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
  6562.         B = NULL;
  6563.  
  6564. #ifndef PRE_SRP_1_4_5
  6565.         /*
  6566.          * The original SRP AUTH implementation did not protect against
  6567.          * tampering of the auth-type-pairs.  Therefore, when the
  6568.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6569.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6570.          * is set we also insert the SSL/TLS client and server finished
  6571.          * messages to ensure that there is no man in the middle attack
  6572.          * underway on the SSL/TLS connection.
  6573.          */
  6574.         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
  6575.             type_check[0] = AUTHTYPE_SRP;
  6576.             type_check[1] = how;
  6577. #ifdef CK_SSL
  6578.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6579.                 ssl_get_client_finished(&type_check[2],12);
  6580.                 ssl_get_server_finished(&type_check[14],12);
  6581.             }
  6582. #endif /* CK_SSL */
  6583.             t_serveraddexdata(ts,type_check,
  6584. #ifdef CK_SSL
  6585.                   ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) ? 26 :
  6586. #endif /* CK_SSL */
  6587.                                2);
  6588.         }
  6589. #endif /* PRE_SRP_1_4_5 */
  6590.  
  6591.         A.data = data;
  6592.         A.len = cnt;
  6593.         ptr = t_servergetkey(ts, &A);
  6594.  
  6595.         if(ptr == NULL) {
  6596.             if (1)
  6597.               printf("Security alert: Trivial session key attempted\r\n");
  6598.             SendSRPAuthSB(SRP_REJECT,
  6599.                           (void *) "Trivial session key detected",
  6600.                           -1
  6601.                           );
  6602.             return(AUTH_FAILURE);
  6603.         }
  6604.         srp_waitresp = 1;
  6605.         return AUTH_SUCCESS;
  6606.  
  6607.     case SRP_RESPONSE:
  6608.         /* Got the response; see if it's correct */
  6609.         if (!srp_waitresp ||
  6610.              ts == NULL
  6611.              ) {
  6612.             if (1)
  6613.               printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  6614.             SendSRPAuthSB(SRP_REJECT,
  6615.                           (void *) "Protocol error: unexpected RESPONSE",
  6616.                           -1
  6617.                           );
  6618.             return(AUTH_FAILURE);
  6619.         }
  6620.         srp_waitresp = 0;       /* we got a response */
  6621.  
  6622.         if (cnt < RESPONSE_LEN) {
  6623.             if (1)
  6624.               printf("Protocol error: malformed response\r\n");
  6625.             SendSRPAuthSB(SRP_REJECT,
  6626.                           (void *) "Protocol error: malformed response",
  6627.                           -1
  6628.                           );
  6629.             return(AUTH_FAILURE);
  6630.         }
  6631.  
  6632.         if (t_serververify(ts, data) == 0) {
  6633.             SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
  6634.             accept_complete = 1;
  6635. #ifdef CK_ENCRYPTION
  6636. #ifdef CK_SSL
  6637.             if (!(ssl_active_flag || tls_active_flag))
  6638. #endif /* CK_SSL */
  6639.             {
  6640.                 hexdump("SRP_RESPONSE ts",ts,sizeof(ts));
  6641.                 hexdump("SRP_RESPONSE session_key",
  6642.                          ts->session_key,
  6643.                          SESSION_KEY_LEN
  6644.                          );
  6645.                 skey.type = SK_GENERIC;
  6646.                 skey.length = SESSION_KEY_LEN;
  6647.                 skey.data = ts->session_key;
  6648.                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  6649.             }
  6650. #endif /* CK_ENCRYPTION */
  6651.             auth_finished(AUTH_VALID);
  6652.         }
  6653.         else {
  6654.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  6655.             auth_finished(AUTH_REJECT);
  6656.             return(AUTH_FAILURE);
  6657.         }
  6658.         return AUTH_SUCCESS;
  6659.  
  6660.     default:
  6661.         printf("Unknown SRP option %d\r\n", data[-1]);
  6662.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  6663.         return(AUTH_FAILURE);
  6664.     }
  6665. }
  6666. #else /* PRE_SRP_1_7_3 */
  6667. static int
  6668. #ifdef CK_ANSIC
  6669. new_srp_reply(int how, unsigned char *data, int cnt)
  6670. #else
  6671. new_srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  6672. #endif
  6673. {
  6674.     data += 4;                          /* Point to status byte */
  6675.     cnt  -= 4;
  6676.  
  6677.     if(cnt-- < 1) {                     /* Matches with data++ */
  6678.         auth_finished(AUTH_REJECT);
  6679.         return AUTH_FAILURE;
  6680.     }
  6681.  
  6682.     switch(*data++) {
  6683.     case SRP_PARAMS: {
  6684.         struct t_num n;
  6685.         struct t_num g;
  6686.         struct t_num s;
  6687.         cstr * A;
  6688.  
  6689.         if(!szUserName) {
  6690.             printf("No username available\r\n");
  6691.             return(auth_resend(AUTHTYPE_SRP));
  6692.         }
  6693.  
  6694.         n.len = srp_decode_length(data);
  6695.         data += 2;
  6696.         cnt -= 2;
  6697.         if(n.len > cnt) {
  6698.             printf("n too long\r\n");
  6699.             return(auth_resend(AUTHTYPE_SRP));
  6700.         }
  6701.         n.data = data;
  6702.         data += n.len;
  6703.         cnt -= n.len;
  6704.  
  6705.         g.len = srp_decode_length(data);
  6706.         data += 2;
  6707.         cnt -= 2;
  6708.         if(g.len > cnt) {
  6709.             printf("g too long\r\n");
  6710.             return(auth_resend(AUTHTYPE_SRP));
  6711.         }
  6712.         g.data = data;
  6713.         data += g.len;
  6714.         cnt -= g.len;
  6715.  
  6716.         s.len = srp_decode_length(data);
  6717.         data += 2;
  6718.         cnt -= 2;
  6719.         if(s.len != cnt) {
  6720.             printf("invalid salt\r\n");
  6721.             return(auth_resend(AUTHTYPE_SRP));
  6722.         }
  6723.         s.data = data;
  6724.         data += s.len;
  6725.         cnt -= s.len;
  6726.  
  6727.         /* If the parameters provided by the server cannot be
  6728.          * validated the following function will fail.
  6729.          */
  6730.         c_srp = SRP_new(SRP_RFC2945_client_method());
  6731.         if(c_srp == NULL ||
  6732.             SRP_set_username(c_srp, szUserName) != SRP_SUCCESS ||
  6733.             SRP_set_params(c_srp, n.data, n.len, g.data, g.len, s.data, s.len) !=
  6734.             SRP_SUCCESS) {
  6735.             printf("SRP Parameter initialization error\r\n");
  6736.             return(auth_resend(AUTHTYPE_SRP));
  6737.         }
  6738.  
  6739.         A = cstr_new();
  6740.         if(SRP_gen_pub(c_srp, &A) != SRP_SUCCESS) {
  6741.             printf("SRP Error generating key exchange\r\n");
  6742.             return(auth_resend(AUTHTYPE_SRP));
  6743.         }
  6744.  
  6745.         SendSRPAuthSB(SRP_EXP, A->data, A->length);
  6746.         cstr_free(A);
  6747.  
  6748.         if ( pwbuf[0] && pwflg ) {
  6749.             printf("SRP using %d-bit modulus for '%s'\r\n",
  6750.                    8 * n.len,
  6751.                    szUserName
  6752.                    );
  6753.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  6754. #ifdef OS2
  6755.             if ( pwcrypt )
  6756.                 ck_encrypt((char *)srp_passwd);
  6757. #endif /* OS2 */
  6758.         } else {
  6759.             extern char * srppwprompt;
  6760.             char prompt[128];
  6761.  
  6762.             if (srppwprompt && srppwprompt[0] &&
  6763.                (strlen(srppwprompt) + strlen(szUserName) - 2) < sizeof(prompt))
  6764.             {
  6765.                 sprintf(prompt,srppwprompt,szUserName);
  6766.             } else {
  6767.                 ckmakxmsg( prompt,sizeof(prompt),
  6768.                            "SRP using ",ckitoa(8*n.len),"-bit modulus\r\n",
  6769.                            szUserName,"'s password: ",
  6770.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  6771.             }
  6772.             readpass(prompt,srp_passwd,sizeof(srp_passwd)-1);
  6773.         }
  6774.  
  6775.         if(SRP_set_auth_password(c_srp, srp_passwd) != SRP_SUCCESS) {
  6776.             memset(srp_passwd, 0, sizeof(srp_passwd));
  6777.             printf("SRP Error setting client password\r\n");
  6778.             return(auth_resend(AUTHTYPE_SRP));
  6779.         }
  6780.         memset(srp_passwd, 0, sizeof(srp_passwd));
  6781.         return AUTH_SUCCESS;
  6782.     }
  6783.     case SRP_CHALLENGE: {
  6784.         char type_check[26];
  6785.         cstr * resp = NULL;
  6786.  
  6787.         if(c_srp == NULL) {
  6788.             printf("SRP protocol error\r\n");
  6789.             return(auth_resend(AUTHTYPE_SRP));
  6790.         }
  6791.  
  6792.         /*
  6793.          * The original SRP AUTH implementation did not protect against
  6794.          * tampering of the auth-type-pairs.  Therefore, when the
  6795.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  6796.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  6797.          * is set we also insert the SSL/TLS client and server finished
  6798.          * messages to ensure that there is no man in the middle attack
  6799.          * underway on the SSL/TLS connection.
  6800.          */
  6801.         if ((how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF) {
  6802.             type_check[0] = AUTHTYPE_SRP;
  6803.             type_check[1] = how;
  6804. #ifdef CK_SSL
  6805.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6806.                 ssl_get_client_finished(&type_check[2],12);
  6807.                 ssl_get_server_finished(&type_check[14],12);
  6808.                 SRP_add_ex_data(c_srp, type_check, 26);
  6809.             } else
  6810. #endif /* CK_SSL */
  6811.                 SRP_add_ex_data(c_srp, type_check, 2);
  6812.         }
  6813.  
  6814.         if(SRP_compute_key(c_srp, &c_key, data, cnt) != SRP_SUCCESS) {
  6815.             printf("SRP ERROR: unable to compute client key\r\n");
  6816.             return(auth_resend(AUTHTYPE_SRP));
  6817.         }
  6818.  
  6819.         resp = cstr_new();
  6820.         if(SRP_respond(c_srp, &resp) != SRP_SUCCESS) {
  6821.             printf("SRP ERROR: unable to compute client response\r\n");
  6822.             return(auth_resend(AUTHTYPE_SRP));
  6823.         }
  6824.         SendSRPAuthSB(SRP_RESPONSE, resp->data, resp->length);
  6825.         cstr_free(resp);
  6826.         srp_waitresp = 1;
  6827.         return AUTH_SUCCESS;
  6828.     }
  6829.     case SRP_ACCEPT: {
  6830. #ifdef CK_ENCRYPTION
  6831.         Session_Key skey;
  6832. #endif /* ENCRYPTION */
  6833.  
  6834.         if(cnt < RESPONSE_LEN || !srp_waitresp || c_srp == NULL) {
  6835.             printf("SRP Protocol error\r\n");
  6836.             return(auth_resend(AUTHTYPE_SRP));
  6837.         }
  6838.         srp_waitresp = 0;
  6839.  
  6840.         if(SRP_verify(c_srp, data, cnt) == SRP_SUCCESS) {
  6841.             printf("SRP accepts you as %s\r\n",szUserName);
  6842.  
  6843. #ifdef CK_SSL
  6844.             if((ssl_active_flag || tls_active_flag) &&
  6845.                 (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  6846.                 printf("TLS session parameters verified by SRP\r\n");
  6847.             } else
  6848. #endif /* CK_SSL */
  6849. #ifdef CK_ENCRYPTION
  6850.             {
  6851.                 skey.type = SK_GENERIC;
  6852.                 skey.length = c_key->length;
  6853.                 skey.data = c_key->data;
  6854.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  6855.                 cstr_clear_free(c_key);
  6856.                 c_key = NULL;
  6857.             }
  6858. #endif /* CK_ENCRYPTION */
  6859.             accept_complete = 1;
  6860.             auth_finished(AUTH_VALID);
  6861.             SRP_free(c_srp);
  6862.             c_srp = NULL;
  6863.             return AUTH_SUCCESS;
  6864.         }
  6865.         else {
  6866.             printf("[ Error: SRP server authentication failed ]\r\n");
  6867.             return(auth_resend(AUTHTYPE_SRP));
  6868.         }
  6869.     }
  6870.     case SRP_REJECT: {
  6871.         char * str=NULL;
  6872.  
  6873.         ckmakmsg(strTmp,sizeof(strTmp),
  6874.                   "SRP refuses authentication for '",szUserName,
  6875.                   "'\r\n",NULL);
  6876.         if (cnt > 0) {
  6877.             int len = strlen(strTmp);
  6878.             if ( len + cnt < sizeof(strTmp) ) {
  6879.                 str = strTmp + strlen(strTmp);
  6880.                 memcpy(str,data,cnt);
  6881.                 str[cnt] = 0;
  6882.             }
  6883.         }
  6884.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  6885.         auth_finished(AUTH_REJECT);
  6886.         return AUTH_FAILURE;
  6887.     }
  6888.     default:
  6889.         printf("Unknown SRP option %d\r\n", data[-1]);
  6890.         return(auth_resend(AUTHTYPE_SRP));
  6891.     }
  6892.     /* NEVER REACHED */
  6893. }
  6894.  
  6895. static int
  6896. #ifdef CK_ANSIC
  6897. new_srp_is(int how, unsigned char *data, int cnt)
  6898. #else
  6899. new_srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  6900. #endif
  6901. {
  6902.     char pbuf[2 * MAXPARAMLEN + 5];
  6903.     char * ptr;
  6904. #ifdef CK_ENCRYPTION
  6905.     Session_Key skey;
  6906. #endif
  6907.     static cstr * B = NULL;             /* Holder for B */
  6908.     struct t_passwd * pass;
  6909.     cstr * resp;
  6910.     char type_check[26];
  6911.  
  6912.     if ((cnt -= 4) < 1) {
  6913.         auth_finished(AUTH_REJECT);
  6914.         return AUTH_FAILURE;
  6915.     }
  6916.  
  6917.     data += 4;
  6918.     cnt  -= 1;
  6919.     switch(*data++) {
  6920.     case SRP_AUTH:
  6921.         /* Send parameters back to client */
  6922.         if(s_srp != NULL) {
  6923.             SRP_free(s_srp);
  6924.             s_srp = NULL;
  6925.         }
  6926.         if (B != NULL) {
  6927.             cstr_free(B);
  6928.             B = NULL;
  6929.         }
  6930.         if(!szUserNameRequested[0]) {
  6931.             if (1)
  6932.                 printf("No username available\r\n");
  6933.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  6934.             auth_finished(AUTH_REJECT);
  6935.             return(AUTH_FAILURE);
  6936.         }
  6937. #ifdef IKSD
  6938. #ifdef CK_LOGIN
  6939.         if (inserver && ckxanon &&
  6940.              !strcmp(szUserNameRequested,"anonymous")) {
  6941.             SendSRPAuthSB(SRP_REJECT, (void *)
  6942.             "anonymous login cannot be performed with Secure Remote Password",
  6943.             -1);
  6944.             auth_finished(AUTH_REJECT);
  6945.             return(AUTH_FAILURE);
  6946.         }
  6947. #endif /* CK_LOGIN */
  6948. #endif /* IKSD */
  6949.         s_srp = SRP_new(SRP_RFC2945_server_method());
  6950.         if(s_srp == NULL) {
  6951.             printf("Error initializing SRP server\r\n");
  6952.             SendSRPAuthSB(SRP_REJECT,
  6953.                           (void *) "SRP server init failed",
  6954.                           -1
  6955.                           );
  6956.             return(AUTH_FAILURE);
  6957.         }
  6958.         pass = gettpnam(szUserNameRequested);
  6959.         if(pass == NULL) {
  6960.             printf("User %s not found\r\n", szUserNameRequested);
  6961.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  6962.             return(AUTH_FAILURE);
  6963.         }
  6964.         if(SRP_set_username(s_srp, szUserNameRequested) != SRP_SUCCESS ||
  6965.             SRP_set_params(s_srp, pass->tc.modulus.data, pass->tc.modulus.len,
  6966.                             pass->tc.generator.data, pass->tc.generator.len,
  6967.                             pass->tp.salt.data, pass->tp.salt.len) != SRP_SUCCESS ||
  6968.             SRP_set_authenticator(s_srp, pass->tp.password.data,
  6969.                                    pass->tp.password.len) != SRP_SUCCESS) {
  6970.             printf("Error initializing SRP parameters\r\n");
  6971.             SendSRPAuthSB(SRP_REJECT, (void *) "SRP parameter init failed", -1);
  6972.             return(AUTH_FAILURE);
  6973.         }
  6974.  
  6975.         ptr = pbuf;
  6976.  
  6977.         srp_encode_length(ptr, pass->tc.modulus.len);
  6978.         ptr += 2;
  6979.         memcpy(ptr, pass->tc.modulus.data, pass->tc.modulus.len);
  6980.         ptr += pass->tc.modulus.len;
  6981.  
  6982.         srp_encode_length(ptr, pass->tc.generator.len);
  6983.         ptr += 2;
  6984.         memcpy(ptr, pass->tc.generator.data, pass->tc.generator.len);
  6985.         ptr += pass->tc.generator.len;
  6986.  
  6987.         srp_encode_length(ptr, pass->tp.salt.len);
  6988.         ptr += 2;
  6989.         memcpy(ptr, pass->tp.salt.data, pass->tp.salt.len);
  6990.         ptr += pass->tp.salt.len;
  6991.  
  6992.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  6993.  
  6994.         if(SRP_gen_pub(s_srp, &B) != SRP_SUCCESS) {
  6995.             printf("Error generating SRP public value\r\n");
  6996.             SendSRPAuthSB(SRP_REJECT, (void *) "SRP_gen_pub failed", -1);
  6997.             return(AUTH_FAILURE);
  6998.         }
  6999.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,UIDBUFLEN);
  7000.         return AUTH_SUCCESS;
  7001.  
  7002.     case SRP_EXP:
  7003.         /* Client is sending A to us.  Compute challenge and expected response. */
  7004.         if(s_srp == NULL || B == NULL) {
  7005.             printf("Protocol error: SRP_EXP unexpected\r\n");
  7006.             SendSRPAuthSB(SRP_REJECT, (void *) "Protocol error: unexpected EXP", -1);
  7007.             return(AUTH_FAILURE);
  7008.         }
  7009.  
  7010.         /* Wait until now to send B, since it contains the key to "u" */
  7011.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->length);
  7012.         cstr_free(B);
  7013.         B = NULL;
  7014.  
  7015.         /*
  7016.          * The original SRP AUTH implementation did not protect against
  7017.          * tampering of the auth-type-pairs.  Therefore, when the
  7018.          * AUTH_ENCRYPT_MASK bits are zero, no extra data is inserted
  7019.          * into the SRP hash computation.  When AUTH_ENCRYPT_START_TLS
  7020.          * is set we also insert the SSL/TLS client and server finished
  7021.          * messages to ensure that there is no man in the middle attack
  7022.          * underway on the SSL/TLS connection.
  7023.          */
  7024.         if ( (how & AUTH_ENCRYPT_MASK) != AUTH_ENCRYPT_OFF ) {
  7025.             type_check[0] = AUTHTYPE_SRP;
  7026.             type_check[1] = how;
  7027. #ifdef CK_SSL
  7028.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_START_TLS) {
  7029.                 ssl_get_client_finished(&type_check[2],12);
  7030.                 ssl_get_server_finished(&type_check[14],12);
  7031.                 SRP_add_ex_data(s_srp, type_check, 26);
  7032.             } else
  7033. #endif /* CK_SSL */
  7034.                 SRP_add_ex_data(s_srp, type_check, 2);
  7035.         }
  7036.  
  7037.         if(SRP_compute_key(s_srp, &s_key, data, cnt) != SRP_SUCCESS) {
  7038.             printf("Security alert: Trivial session key attempted\r\n");
  7039.             SendSRPAuthSB(SRP_REJECT, (void *) "Trivial session key detected", -1);
  7040.             return(AUTH_FAILURE);
  7041.         }
  7042.         srp_waitresp = 1;
  7043.         return AUTH_SUCCESS;
  7044.  
  7045.     case SRP_RESPONSE:
  7046.         /* Got the response; see if it's correct */
  7047.         if (!srp_waitresp || s_srp == NULL) {
  7048.             if (1)
  7049.               printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  7050.             SendSRPAuthSB(SRP_REJECT,
  7051.                           (void *) "Protocol error: unexpected RESPONSE",
  7052.                           -1
  7053.                           );
  7054.             return(AUTH_FAILURE);
  7055.         }
  7056.         srp_waitresp = 0;       /* we got a response */
  7057.  
  7058.         if (cnt < RESPONSE_LEN) {
  7059.             if (1)
  7060.               printf("Protocol error: malformed response\r\n");
  7061.             SendSRPAuthSB(SRP_REJECT,
  7062.                           (void *) "Protocol error: malformed response",
  7063.                           -1
  7064.                           );
  7065.             return(AUTH_FAILURE);
  7066.         }
  7067.  
  7068.         if(SRP_verify(s_srp, data, cnt) == SRP_SUCCESS) {
  7069.             resp = cstr_new();
  7070.             if(SRP_respond(s_srp, &resp) != SRP_SUCCESS) {
  7071.                 printf("Error computing response\r\n");
  7072.                 SendSRPAuthSB(SRP_REJECT,
  7073.                               (void *) "Error computing response", -1);
  7074.                 return(AUTH_FAILURE);
  7075.             }
  7076.             SendSRPAuthSB(SRP_ACCEPT, resp->data, resp->length);
  7077.             accept_complete = 1;
  7078.             cstr_free(resp);
  7079.  
  7080. #ifdef CK_ENCRYPTION
  7081. #ifdef CK_SSL
  7082.             if (!(ssl_active_flag || tls_active_flag))
  7083. #endif /* CK_SSL */
  7084.             {
  7085.                 skey.type = SK_GENERIC;
  7086.                 skey.length = s_key->length;
  7087.                 skey.data = s_key->data;
  7088.                 encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  7089.                 cstr_clear_free(s_key);
  7090.                 s_key = NULL;
  7091.             }
  7092. #endif /* CK_ENCRYPTION */
  7093.             auth_finished(AUTH_VALID);
  7094.         }
  7095.         else {
  7096.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  7097.             auth_finished(AUTH_REJECT);
  7098.             return(AUTH_FAILURE);
  7099.         }
  7100.         return AUTH_SUCCESS;
  7101.  
  7102.     default:
  7103.         printf("Unknown SRP option %d\r\n", data[-1]);
  7104.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  7105.         return(AUTH_FAILURE);
  7106.     }
  7107. }
  7108. #endif /* PRE_SRP_1_7_3 */
  7109. #endif /* SRP */
  7110.  
  7111. #ifdef KRB5
  7112. #ifdef KINIT
  7113. /*
  7114.  * clients/kinit/kinit.c
  7115.  *
  7116.  * Copyright 1990 by the Massachusetts Institute of Technology.
  7117.  * All Rights Reserved.
  7118.  *
  7119.  * Export of this software from the United States of America may
  7120.  *   require a specific license from the United States Government.
  7121.  *   It is the responsibility of any person or organization contemplating
  7122.  *   export to obtain such a license before exporting.
  7123.  *
  7124.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  7125.  * distribute this software and its documentation for any purpose and
  7126.  * without fee is hereby granted, provided that the above copyright
  7127.  * notice appear in all copies and that both that copyright notice and
  7128.  * this permission notice appear in supporting documentation, and that
  7129.  * the name of M.I.T. not be used in advertising or publicity pertaining
  7130.  * to distribution of the software without specific, written prior
  7131.  * permission.  M.I.T. makes no representations about the suitability of
  7132.  * this software for any purpose.  It is provided "as is" without express
  7133.  * or implied warranty.
  7134.  *
  7135.  *
  7136.  * Initialize a credentials cache.
  7137.  */
  7138.  
  7139. #define KRB5_DEFAULT_OPTIONS 0
  7140. #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
  7141.  
  7142. static krb5_data tgtname = {
  7143. #ifndef HEIMDAL
  7144.     0,
  7145. #endif /* HEIMDAL */
  7146.     KRB5_TGS_NAME_SIZE,
  7147.     KRB5_TGS_NAME
  7148. };
  7149.  
  7150. /* Internal prototypes */
  7151. _PROTOTYP(static krb5_error_code krb5_validate_tgt,
  7152.         (krb5_context, krb5_ccache,krb5_principal, krb5_data *));
  7153. _PROTOTYP(static krb5_error_code krb5_renew_tgt,
  7154.         (krb5_context, krb5_ccache,
  7155.                         krb5_principal, krb5_data *));
  7156. _PROTOTYP(static krb5_error_code krb5_tgt_gen,
  7157.         (krb5_context, krb5_ccache,
  7158.                         krb5_principal, krb5_data *, int opt));
  7159.  
  7160. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7161. static krb5_error_code KRB5_CALLCONV
  7162. ck_krb5_prompter( krb5_context context,
  7163.                   void *data,
  7164.                   const char *name,
  7165.                   const char *banner,
  7166.                   int num_prompts,
  7167.                   krb5_prompt prompts[])
  7168. {
  7169.     krb5_error_code     errcode = 0;
  7170.     int                 i;
  7171.     char * prompt = NULL;
  7172.     int    len = 0, blen=0, nlen=0;
  7173.  
  7174.     debug(F110,"ck_krb5_prompter name",name,0);
  7175.     debug(F110,"ck_krb5_prompter banner",banner,0);
  7176.     debug(F101,"ck_krb5_prompter num_prompts","",num_prompts);
  7177.  
  7178.     if (name)
  7179.         nlen = strlen(name)+2;
  7180.  
  7181.     if (banner)
  7182.         blen = strlen(banner)+2;
  7183.  
  7184.     for (i = 0; i < num_prompts; i++) {
  7185.         debug(F111,"ck_krb5_prompter prompt",prompts[i].prompt,i);
  7186.  
  7187.         if ( prompt && len < (nlen + blen + strlen(prompts[i].prompt)+2) ) {
  7188.             free(prompt);
  7189.             prompt = NULL;
  7190.         }
  7191.         if ( !prompt )
  7192.             prompt = (char *)malloc(nlen + blen + strlen(prompts[i].prompt)+2);
  7193.         if ( !prompt ) {
  7194.             errcode = KRB5_RC_MALLOC;
  7195.             goto cleanup;
  7196.         }
  7197.         len = nlen + blen + strlen(prompts[i].prompt)+2;
  7198.         ckmakxmsg(prompt,len,
  7199.                  name?name:"",
  7200.                  name?"\r\n":"",
  7201.                  banner?banner:"",
  7202.                  banner?"\r\n":"",
  7203.                  prompts[i].prompt,
  7204.                  ": ",NULL,NULL,NULL,NULL,NULL,NULL);
  7205.  
  7206.         memset(prompts[i].reply->data, 0, prompts[i].reply->length);
  7207.         if (prompts[i].hidden) {
  7208.             readpass(prompt, prompts[i].reply->data,
  7209.                       prompts[i].reply->length);
  7210.         } else {
  7211.             readtext(prompt, prompts[i].reply->data,
  7212.                       prompts[i].reply->length);
  7213.         }
  7214.         prompts[i].reply->length = strlen(prompts[i].reply->data);
  7215.     }
  7216.  
  7217.   cleanup:
  7218.     if ( prompt )
  7219.         free(prompt);
  7220.     if (errcode) {
  7221.         for (i = 0; i < num_prompts; i++) {
  7222.             memset(prompts[i].reply->data, 0, prompts[i].reply->length);
  7223.         }
  7224.     }
  7225.     return errcode;
  7226. }
  7227.  
  7228. /*
  7229.  *      I'm not really sure what to do with this.  The NRL DLLs use a
  7230.  *      different interface for the krb5_prompter callback.  It has
  7231.  *      one less parameter.   This is going to be ugly.
  7232.  */
  7233. static krb5_error_code KRB5_CALLCONV
  7234. ck_NRL_krb5_prompter( krb5_context context,
  7235.                       const char *name,
  7236.                       const char *banner,
  7237.                       int num_prompts,
  7238.                       krb5_prompt prompts[])
  7239. {
  7240.     return(ck_krb5_prompter(context,NULL,name,banner,num_prompts,prompts));
  7241. }
  7242. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7243.  
  7244. #define NO_KEYTAB
  7245.  
  7246. int
  7247. #ifdef CK_ANSIC
  7248. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init,
  7249.                  struct krb4_init_data * k4_init)
  7250. #else
  7251. ck_krb5_initTGT(op,init,k4_init)
  7252.     krb_op_data * op; struct krb5_init_data * init;
  7253.     struct krb4_init_data * k4_init;
  7254. #endif /* CK_ANSIC*/
  7255. {
  7256.     krb5_context kcontext;
  7257.     krb5_ccache ccache = NULL;
  7258.     krb5_deltat lifetime = KRB5_DEFAULT_LIFE;   /* -l option */
  7259.     krb5_timestamp starttime = 0;
  7260.     krb5_deltat rlife = 0;
  7261.     int options = KRB5_DEFAULT_OPTIONS;
  7262.     int option;
  7263.     int errflg = 0;
  7264.     krb5_error_code code;
  7265.     krb5_principal me=NULL;
  7266.     krb5_principal server=NULL;
  7267.     krb5_creds my_creds;
  7268.     krb5_timestamp now;
  7269. #ifndef HEIMDAL
  7270.     krb5_address **addrs = (krb5_address **)0;
  7271. #endif /* HEIMDAL */
  7272.     int addr_count=0;
  7273.     int i,j;
  7274. #ifndef NO_KEYTAB
  7275.     int use_keytab = 0;                 /* -k option */
  7276.     krb5_keytab keytab = NULL;
  7277. #endif /* NO_KEYTAB */
  7278.     struct passwd *pw = 0;
  7279.     int pwsize;
  7280.     char *client_name=NULL, principal[256]="", realm[256]="", numstr[40]="";
  7281.     char *password=NULL, passwd[80]="";
  7282. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7283.     krb5_get_init_creds_opt opts;
  7284. #endif
  7285.     char * name;
  7286.     int len;
  7287.  
  7288.     if ( !ck_krb5_is_installed() )
  7289.         return(-1);
  7290.  
  7291. #ifdef COMMENT
  7292.     printf("Kerberos V initialization\r\n");
  7293. #endif /* COMMENT */
  7294.  
  7295.     code = krb5_init_context(&kcontext);
  7296.     if (code) {
  7297.         com_err("krb5_kinit",code,"while init_context");
  7298.         krb5_errno = code;
  7299.         makestr(&krb5_errmsg,error_message(krb5_errno));
  7300.         return(-1);
  7301.     }
  7302.  
  7303.     debug(F110,"krb5_init","krb5_init_context",0);
  7304.  
  7305.     if ((code = krb5_timeofday(kcontext, &now))) {
  7306.         com_err("krb5_kinit",code,"while getting time of day");
  7307.         goto exit_k5_init;
  7308.     }
  7309.  
  7310. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7311.     memset(&opts, 0, sizeof(opts));
  7312.     krb5_get_init_creds_opt_init(&opts);
  7313.     debug(F110,"krb5_init","krb5_get_init_creds_opt_init",0);
  7314. #endif
  7315.  
  7316.     if ( init->renewable ) {
  7317.         options |= KDC_OPT_RENEWABLE;
  7318.         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->renewable),"m",NULL,NULL);
  7319. #ifdef HEIMDAL
  7320.         code = -1;
  7321. #else /* HEIMDAL */
  7322.         code = krb5_string_to_deltat(numstr, &rlife);
  7323. #endif /* HEIMDAL */
  7324.         if (code != 0 || rlife == 0) {
  7325.             printf("Bad renewable time value %s\r\n", numstr);
  7326.             errflg++;
  7327.         }
  7328. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7329.         krb5_get_init_creds_opt_set_renew_life(&opts, rlife);
  7330. #endif
  7331.     }
  7332.     if ( init->renew ) {
  7333.         /* renew the ticket */
  7334.         options |= KDC_OPT_RENEW;
  7335.     }
  7336.  
  7337.     if ( init->validate ) {
  7338.         /* validate the ticket */
  7339.         options |= KDC_OPT_VALIDATE;
  7340.     }
  7341.     if ( init->proxiable ) {
  7342.         options |= KDC_OPT_PROXIABLE;
  7343. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7344.         krb5_get_init_creds_opt_set_proxiable(&opts, 1);
  7345. #endif
  7346.     }
  7347.     if ( init->forwardable ) {
  7348.         options |= KDC_OPT_FORWARDABLE;
  7349. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7350.         krb5_get_init_creds_opt_set_forwardable(&opts, 1);
  7351. #endif
  7352.     }
  7353. #ifndef NO_KEYTAB
  7354.     if (  ) {
  7355.         use_keytab = 1;
  7356.     }
  7357.     if (  ) {
  7358.         if (keytab == NULL && keytab_name != NULL) {
  7359.             code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
  7360.             if (code != 0) {
  7361.                 debug(F111,"krb5_init resolving keytab",
  7362.                          keytab_name,code);
  7363.                 errflg++;
  7364.             }
  7365.         }
  7366.     }
  7367. #endif /* NO_KEYTAB */
  7368.     if ( init->lifetime ) {
  7369.         ckmakmsg(numstr,sizeof(numstr),ckitoa(init->lifetime),"m",NULL,NULL);
  7370. #ifdef HEIMDAL
  7371.         code = -1;
  7372. #else /* HEIMDAL */
  7373.         code = krb5_string_to_deltat(numstr, &lifetime);
  7374. #endif /* HEIMDAL */
  7375.         if (code != 0 || lifetime == 0) {
  7376.             printf("Bad lifetime value %s\r\n", numstr);
  7377.             errflg++;
  7378.         }
  7379. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7380.         krb5_get_init_creds_opt_set_tkt_life(&opts, lifetime);
  7381. #endif
  7382.     }
  7383.     if ( init->postdate ) {
  7384.         /* Convert cmdate() to a time_t value */
  7385.         struct tm * time_tm;
  7386.         struct tm * cmdate2tm(char *,int);
  7387.         time_tm = cmdate2tm(init->postdate,0);
  7388.         if ( time_tm )
  7389.             starttime = (krb5_timestamp) mktime(time_tm);
  7390.  
  7391.         if (code != 0 || starttime == 0 || starttime == -1) {
  7392.             krb5_deltat ktmp;
  7393. #ifdef HEIMDAL
  7394.             code = -1;
  7395. #else /* HEIMDAL */
  7396.             code = krb5_string_to_deltat(init->postdate, &ktmp);
  7397. #endif /* HEIMDAL */
  7398.             if (code == 0 && ktmp != 0) {
  7399.                 starttime = now + ktmp;
  7400.                 options |= KDC_OPT_POSTDATED;
  7401.             } else {
  7402.                 printf("Bad postdate start time value %s\r\n",
  7403.                         init->postdate);
  7404.                 errflg++;
  7405.             }
  7406.         } else {
  7407.             options |= KDC_OPT_POSTDATED;
  7408.         }
  7409.     }
  7410.  
  7411.     debug(F110,"krb5_init searching for ccache",op->cache,0);
  7412.  
  7413.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  7414.     if (code != 0) {
  7415.         com_err("krb5_kinit",code,"while getting default ccache");
  7416.         goto exit_k5_init;
  7417.     }
  7418.  
  7419.     /* This is our realm unless it is changed */
  7420.     ckstrncpy(realm,init->realm ? init->realm : krb5_d_realm, 256);
  7421.  
  7422. #ifdef BETATEST
  7423.     /* This code is going to take the realm and attempt to correct */
  7424.     /* the case.                                                   */
  7425.     {
  7426.         profile_t profile;
  7427.  
  7428.         code = krb5_get_profile(kcontext, &profile);
  7429.         if ( !code ) {
  7430.             const char  *names[4];
  7431.             char ** realms;
  7432.             int found = 0;
  7433.  
  7434.             names[0] = "realms";
  7435.             names[1] = NULL;
  7436.  
  7437.             code = profile_get_subsection_names(profile,names,&realms);
  7438.             if ( code == 0 ) {
  7439.                 int i=0;
  7440.                 while ( realms[i] ) {
  7441.                     if (ckstrcmp(realm,realms[i],-1,0) == 0) {
  7442.                         strcpy(realm,realms[i]);
  7443.                         found = 1;
  7444.                         break;
  7445.                     }
  7446.                     i++;
  7447.                 }
  7448.             }
  7449.  
  7450. #ifdef CK_DNS_SRV
  7451.             if ( !found ) {
  7452.                 char * dns_realm = NULL;
  7453.  
  7454.                 /* We did not find the realm in the profile so let's try DNS */
  7455.                 locate_txt_rr("_kerberos",realm,&dns_realm);
  7456.                 if ( dns_realm &&
  7457.                      ckstrcmp(realm,dns_realm,-1,0) == 0 &&
  7458.                      ckstrcmp(realm,dns_realm,-1,1) != 0
  7459.                      ) {
  7460.                     ckstrncpy(realm,dns_realm,256);
  7461.                     free(dns_realm);
  7462.                 }
  7463.             }
  7464. #endif /* CK_DNS_SRV */
  7465.         }
  7466.  
  7467.         if (init->realm &&
  7468.              ckstrcmp(realm,init->realm,-1,0) == 0 &&
  7469.              ckstrcmp(realm,init->realm,-1,1) != 0)
  7470.             strcpy(init->realm,realm);
  7471.         if (ckstrcmp(realm,krb5_d_realm,-1,0) == 0 &&
  7472.              ckstrcmp(realm,krb5_d_realm,-1,1) != 0)
  7473.             strcpy(krb5_d_realm,realm);
  7474.     }
  7475. #endif /* BETATEST */
  7476.  
  7477.     if (init->principal == NULL) {       /* No principal name specified */
  7478. #ifndef NO_KEYTAB
  7479.         if (use_keytab) {
  7480.             /* Use the default host/service name */
  7481.             code = krb5_sname_to_principal(kcontext, NULL, NULL,
  7482.                                             KRB5_NT_SRV_HST, &me);
  7483.             if (code == 0 &&
  7484.                 krb5_princ_realm(kcontext, me)->length < sizeof(realm))
  7485.             {
  7486.                 /* Save the realm */
  7487.                 memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  7488.                         krb5_princ_realm(kcontext, me)->length); /* safe */
  7489.                 realm[krb5_princ_realm(kcontext, me)->length]='\0';
  7490.             } else {
  7491.                 com_err("krb5_kinit",
  7492.                         code,
  7493.                         "when creating default server principal name");
  7494.                 goto exit_k5_init;
  7495.             }
  7496.         } else
  7497. #endif /* NO_KEYTAB */
  7498.         {
  7499.             int len;
  7500.             char * name;
  7501.  
  7502.             /* Get default principal from cache if one exists */
  7503.             code = krb5_cc_get_principal(kcontext, ccache, &me);
  7504. #ifdef HEIMDAL
  7505.             name = me->realm;
  7506.             len = strlen(name);
  7507. #else /* HEIMDAL */
  7508.             len = krb5_princ_realm(kcontext, me)->length;
  7509.             name = krb5_princ_realm(kcontext, me)->data;
  7510. #endif /* HEIMDAL */
  7511.             if (code == 0 && len < sizeof(realm))
  7512.             {
  7513.                 /* Save the realm */
  7514.                 memcpy(realm,name,len); /* safe */
  7515.                 realm[len]='\0';
  7516.             } else {
  7517. #ifdef HAVE_PWD_H
  7518.                 /* Else search passwd file for client */
  7519.  
  7520.                 pw = getpwuid((int) getuid());
  7521.                 if (pw) {
  7522.                     char princ_realm[256];
  7523.                     if ( (strlen(pw->pw_name) + strlen(realm) + 1) > 255 )
  7524.                         goto exit_k5_init;
  7525.  
  7526.                     ckstrncpy(principal,pw->pw_name,256);
  7527.                     ckstrncpy(princ_realm,pw->pw_name,256);
  7528.                     ckstrncat(princ_realm,"@",256);
  7529.                     ckstrncat(princ_realm,realm,256);
  7530.  
  7531.                     if ((code = krb5_parse_name(kcontext,princ_realm,&me))) {
  7532.                         krb5_errno = code;
  7533.                         com_err("krb5_kinit",code,"when parsing name",
  7534.                                   princ_realm);
  7535.                         goto exit_k5_init;
  7536.                     }
  7537.                 } else {
  7538.                     printf(
  7539.                         "Unable to identify user from password file\r\n");
  7540.                     goto exit_k5_init;
  7541.                 }
  7542. #else /* HAVE_PWD_H */
  7543.                 printf("Unable to identify user\r\n");
  7544.                 goto exit_k5_init;
  7545. #endif /* HAVE_PWD_H */
  7546.             }
  7547.         }
  7548.  
  7549. #ifdef HEIMDAL
  7550.         len = me->name.name_string.len;
  7551.         name = *me->name.name_string.val;
  7552. #else /* HEIMDAL */
  7553.         len = krb5_princ_name(kcontext, me)->length;
  7554.         name = krb5_princ_name(kcontext, me)->data;
  7555. #endif /* HEIMDAL */
  7556.         if ( len < sizeof(principal) ) {
  7557.             memcpy(principal,name,len);     /* safe */
  7558.             principal[len]='\0';
  7559.         }
  7560.     } /* Use specified name */
  7561.     else {
  7562.         char princ_realm[256];
  7563.         if ( (strlen(init->principal) +
  7564.               (init->instance ? strlen(init->instance)+1 : 0) +
  7565.               strlen(realm)
  7566.               + 2) > 255 )
  7567.              goto exit_k5_init;
  7568.  
  7569.         ckstrncpy(principal,init->principal,256);
  7570.         ckstrncpy(princ_realm,init->principal,256);
  7571.         if (init->instance) {
  7572.             ckstrncat(princ_realm,"/",256);
  7573.             ckstrncat(princ_realm,init->instance,256);
  7574.         }
  7575.         if (realm[0]) {
  7576.           ckstrncat(princ_realm,"@",256);
  7577.           ckstrncat(princ_realm,realm,256);
  7578.         }
  7579.         if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
  7580.             com_err("krb5_kinit",code,"when parsing name",princ_realm);
  7581.             goto exit_k5_init;
  7582.         }
  7583.     }
  7584.  
  7585.     if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
  7586.         com_err("krb5_kinit",code,"when unparsing name");
  7587.         goto exit_k5_init;
  7588.     }
  7589.     debug(F110,"krb5_init client_name",client_name,0);
  7590.  
  7591.  
  7592.     memset((char *)&my_creds, 0, sizeof(my_creds));
  7593.     my_creds.client = me;
  7594.  
  7595.     if (init->service == NULL) {
  7596.         if ((code =
  7597.              krb5_build_principal_ext(kcontext,
  7598.                                       &server,
  7599.                                       strlen(realm),realm,
  7600.                                       tgtname.length, tgtname.data,
  7601.                                       strlen(realm),realm,
  7602.                                       0))) {
  7603.             com_err("krb5_kinit",code,"while building server name");
  7604.             goto exit_k5_init;
  7605.         }
  7606.     } else {
  7607.         if (code = krb5_parse_name(kcontext, init->service, &server)) {
  7608.             com_err("krb5_kinit",code,"while parsing service name",
  7609.                     init->service);
  7610.             goto exit_k5_init;
  7611.         }
  7612.     }
  7613.  
  7614.     my_creds.server = server;
  7615.  
  7616.     if (options & KDC_OPT_POSTDATED) {
  7617.         my_creds.times.starttime = starttime;
  7618.         my_creds.times.endtime = starttime + lifetime;
  7619.     } else {
  7620.         my_creds.times.starttime = 0;   /* start timer when request
  7621.                                            gets to KDC */
  7622.         my_creds.times.endtime = now + lifetime;
  7623.     }
  7624.     if (options & KDC_OPT_RENEWABLE) {
  7625.         my_creds.times.renew_till = now + rlife;
  7626.     } else
  7627.         my_creds.times.renew_till = 0;
  7628.  
  7629.     if (options & KDC_OPT_VALIDATE) {
  7630.         krb5_data outbuf;
  7631.  
  7632. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7633.         code = krb5_get_validated_creds(kcontext,
  7634.                                         &my_creds, me, ccache, init->service);
  7635.         if ( code == -1 )
  7636. #endif
  7637.         {
  7638. #ifdef HEIMDAL
  7639.             printf("?validate not implemented\r\n");
  7640.             code = -1;
  7641.             goto exit_k5_init;
  7642. #else /* HEIMDAL */
  7643.             code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
  7644. #endif /* HEIMDAL */
  7645.         }
  7646.         if (code) {
  7647.             com_err("krb5_kinit",code,"validating tgt");
  7648.             goto exit_k5_init;
  7649.         }
  7650.         /* should be done... */
  7651.         goto exit_k5_init;
  7652.     }
  7653.  
  7654.     if (options & KDC_OPT_RENEW) {
  7655.         krb5_data outbuf;
  7656.  
  7657. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7658.         code = krb5_get_renewed_creds(kcontext,
  7659.                                       &my_creds, me, ccache, init->service);
  7660.         if ( code == -1 )
  7661. #endif
  7662.         {
  7663. #ifdef HEIMDAL
  7664.             printf("?renew not implemented\r\n");
  7665.             code = -1;
  7666.             goto exit_k5_init;
  7667. #else /* HEIMDAL */
  7668.             code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
  7669. #endif /* HEIMDAL */
  7670.         }
  7671.         if (code) {
  7672.             com_err("krb5_kinit",code,"while renewing tgt");
  7673.             goto exit_k5_init;
  7674.         }
  7675.         /* should be done... */
  7676.         goto exit_k5_init;
  7677.     }
  7678.  
  7679. #ifndef HEIMDAL
  7680.     if ( init->addrs && !init->no_addresses ) {
  7681.         /* construct an array of krb5_address structs to pass to get_in_tkt */
  7682.         /* include both the local ip addresses as well as any other that    */
  7683.         /* are specified.                                                   */
  7684.         unsigned long ipaddr;
  7685.  
  7686.         for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
  7687.             if ( init->addrs[addr_count] == NULL )
  7688.                 break;
  7689.  
  7690.         if (addr_count > 0) {
  7691.             krb5_address ** local_addrs=NULL;
  7692.             krb5_os_localaddr(kcontext, &local_addrs);
  7693.             i = 0;
  7694.             while ( local_addrs[i] )
  7695.                 i++;
  7696.             addr_count += i;
  7697.  
  7698.             addrs = (krb5_address **)
  7699.               malloc((addr_count+1) * sizeof(krb5_address));
  7700.             if ( !addrs ) {
  7701.                 krb5_free_addresses(kcontext, local_addrs);
  7702.                 goto exit_k5_init;
  7703.             }
  7704.             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
  7705.             i = 0;
  7706.             while ( local_addrs[i] ) {
  7707.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  7708.                 if (addrs[i] == NULL) {
  7709.                     krb5_free_addresses(kcontext, local_addrs);
  7710.                     goto exit_k5_init;
  7711.                 }
  7712.  
  7713.                 addrs[i]->magic = local_addrs[i]->magic;
  7714.                 addrs[i]->addrtype = local_addrs[i]->addrtype;
  7715.                 addrs[i]->length = local_addrs[i]->length;
  7716.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  7717.                 if (!addrs[i]->contents) {
  7718.                     krb5_free_addresses(kcontext, local_addrs);
  7719.                     goto exit_k5_init;
  7720.                 }
  7721.  
  7722.                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
  7723.                         local_addrs[i]->length);        /* safe */
  7724.                 i++;
  7725.             }
  7726.             krb5_free_addresses(kcontext, local_addrs);
  7727.  
  7728.             for ( j=0;i<addr_count;i++,j++ ) {
  7729.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  7730.                 if (addrs[i] == NULL)
  7731.                     goto exit_k5_init;
  7732.  
  7733.                 addrs[i]->magic = KV5M_ADDRESS;
  7734.                 addrs[i]->addrtype = AF_INET;
  7735.                 addrs[i]->length = 4;
  7736.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  7737.                 if (!addrs[i]->contents)
  7738.                     goto exit_k5_init;
  7739.  
  7740.                 ipaddr = inet_addr(init->addrs[j]);
  7741.                 memcpy(addrs[i]->contents,&ipaddr,4);   /* safe */
  7742.             }
  7743. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7744.             krb5_get_init_creds_opt_set_address_list(&opts,addrs);
  7745. #endif
  7746.         }
  7747.      }
  7748. #endif /* !HEIMDAL */
  7749. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7750.     if ( init->no_addresses )
  7751.         krb5_get_init_creds_opt_set_address_list(&opts,NULL);
  7752. #endif
  7753.  
  7754. #ifndef NO_KEYTAB
  7755.     if (!use_keytab)
  7756. #endif
  7757.     {
  7758.         if ( init->password ) {
  7759.             pwsize = strlen(init->password);
  7760.             if ( pwsize )
  7761.                 password = init->password;
  7762.         } else if (init->getk4 && k4_init) {
  7763.             /* When we are requesting that K4 tickets be automatically */
  7764.             /* acquired when K5 tickets are acquired, we must get the  */
  7765.             /* password up front.                                      */
  7766.             char prmpt[256];
  7767.             extern char * k5prprompt;
  7768.             extern char * k5pwprompt;
  7769.  
  7770.             if ( k5pwprompt && k5pwprompt[0] &&
  7771.                  (strlen(k5pwprompt) + strlen(principal) +
  7772.                   strlen(realm) - 4) < sizeof(prmpt)) {
  7773.                 sprintf(prmpt,k5pwprompt,principal,realm);
  7774.             } else
  7775.                 ckmakxmsg(prmpt,sizeof(prmpt),
  7776.                            k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  7777.                            "Kerberos 5 Password for ",
  7778.                            principal,"@",realm,": ",
  7779.                            NULL,NULL,NULL,NULL,NULL,NULL,NULL
  7780.                            );
  7781.             readpass(prmpt,passwd,80);
  7782.             password = passwd;
  7783.  
  7784.             if ( k4_init->password == NULL )
  7785.                 makestr(&k4_init->password,passwd);
  7786.         }
  7787. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7788.         debug(F100,"krb5_init calling krb5_get_init_creds_password()","",0);
  7789. #ifdef OS2
  7790.         if ( is_NRL_KRB5() )
  7791.             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
  7792.                                                  password,
  7793.                                                  (void *)ck_NRL_krb5_prompter,
  7794.                                                  NULL,
  7795.                                                  starttime, init->service,
  7796.                                                  &opts);
  7797.         else
  7798. #endif /* OS2 */
  7799.             code = krb5_get_init_creds_password(kcontext, &my_creds, me,
  7800.                                                  password,
  7801.                                                  ck_krb5_prompter,
  7802.                                                  NULL,
  7803.                                                  starttime, init->service,
  7804.                                                  &opts);
  7805.         debug(F111,"krb5_init","krb5_get_init_creds_password()",code);
  7806.  
  7807.         if ( code == -1 )
  7808.         {
  7809.             if (!password) {
  7810.                 char prmpt[256];
  7811.                 ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
  7812.                           client_name,": ",NULL);
  7813.                 readpass(prmpt,passwd,80);
  7814.                 password = passwd;
  7815.             }
  7816.  
  7817.             if ( !password[0] ) {
  7818.                 debug(F111,"krb5_init","no password specified",0);
  7819.                 printf("A password must be specified for %s.\r\n",client_name);
  7820.                 goto exit_k5_init;
  7821.             }
  7822.             code = krb5_get_in_tkt_with_password(kcontext, options,
  7823. #ifdef HEIMDAL
  7824.                                                   NULL,
  7825. #else /* HEIMDAL */
  7826.                                             init->no_addresses ? NULL :addrs,
  7827. #endif /* HEIMDAL */
  7828.                                                   NULL, NULL,
  7829.                                                   password,
  7830.                                                   NULL, &my_creds, NULL);
  7831.             if ( code )
  7832.                 debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
  7833.         }
  7834. #else /* KRB5_HAVE_GET_INIT_CREDS */
  7835.         if (!password) {
  7836.             char prmpt[256];
  7837.             ckmakmsg(prmpt,sizeof(prmpt),"Kerberos 5 Password for ",
  7838.                       client_name,": ",NULL);
  7839.             readpass(prmpt,passwd,80);
  7840.             password = passwd;
  7841.         }
  7842.  
  7843.         if ( !password[0] ) {
  7844.             debug(F111,"krb5_init","no password specified",0);
  7845.             printf("A password must be specified for %s.\r\n",client_name);
  7846.             goto exit_k5_init;
  7847.         }
  7848.         code = krb5_get_in_tkt_with_password(kcontext, options,
  7849. #ifdef HEIMDAL
  7850.                                               NULL,
  7851. #else /* HEIMDAL */
  7852.                                             init->no_addresses ? NULL :addrs,
  7853. #endif /* HEIMDAL */
  7854.                                               NULL, NULL,
  7855.                                               password,
  7856.                                               NULL, &my_creds, NULL);
  7857.         if ( code )
  7858.             debug(F111,"krb5_init","krb5_get_in_tkt_with_password()",code);
  7859. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7860.  
  7861.         if ( init->password && pwsize > 0 )
  7862.             memset(init->password, 0, pwsize);
  7863.         memset(passwd,0,80);
  7864.     }
  7865. #ifndef NO_KEYTAB
  7866.     else {
  7867. #ifdef KRB5_HAVE_GET_INIT_CREDS
  7868.         code = krb5_get_init_creds_keytab(kcontext, &my_creds, me, keytab,
  7869.                                            starttime, init->service,
  7870.                                            &opts);
  7871. #ifdef OS2
  7872.         if ( code == -1)
  7873.             code = krb5_get_in_tkt_with_keytab(kcontext, options,
  7874.                                            init->no_addresses ? NULL :addrs,
  7875.                                                 NULL, NULL, keytab, NULL,
  7876.                                                 &my_creds, 0);
  7877. #endif /* OS2 */
  7878. #else /* KRB5_HAVE_GET_INIT_CREDS */
  7879.         code = krb5_get_in_tkt_with_keytab(kcontext, options,
  7880. #ifdef HEIMDAL
  7881.                                                   NULL,
  7882. #else /* HEIMDAL */
  7883.                                             init->no_addresses ? NULL :addrs,
  7884. #endif /* HEIMDAL */
  7885.                                             NULL, NULL, keytab, NULL,
  7886.                                             &my_creds, 0);
  7887. #endif /* KRB5_HAVE_GET_INIT_CREDS */
  7888.     }
  7889. #endif
  7890.  
  7891.     if (code) {
  7892.         switch (code) {
  7893.         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
  7894.             printf("Password incorrect\r\n");
  7895.             goto exit_k5_init;
  7896.         case KRB5KRB_AP_ERR_V4_REPLY:
  7897.             if (init->getk4 && k4_init) {
  7898.                 printf("Kerberos 5 Tickets not support by server.  ");
  7899.                 printf("A version 4 Ticket will be requested.\r\n");
  7900.             }
  7901.             goto exit_k5_init;
  7902.         default:
  7903.             goto exit_k5_init;
  7904.         }
  7905.     }
  7906.  
  7907.     debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
  7908.  
  7909.     code = krb5_cc_initialize (kcontext, ccache, me);
  7910.     if ( code == KRB5_CC_BADNAME ) {
  7911.         /* This is a really ugly hack that should not have to be here.
  7912.          * krb5_cc_initialize should not fail with an error if the
  7913.          * cache already exists.  The reason the problem is occuring
  7914.          * is that the krb5 library is no longer calling cc_destroy()
  7915.          * when cc_initialize() is called and the CCAPI implementation
  7916.          * on Windows has not yet been corrected to handle it.  To
  7917.          * ensure that K95 will continue to work with both we will call
  7918.          * cc_destroy() if the cc_initialize() call fails with a BADNAME
  7919.          * error.  If the cc_destroy() is successful, we will try again.
  7920.          */
  7921.  
  7922.         debug(F100,"krb5_init calling krb5_cc_destroy()","",0);
  7923.         code = krb5_cc_destroy (kcontext, ccache);
  7924.         if ( !code ) {
  7925.             debug(F100,"krb5_init calling k5_get_ccache()","",0);
  7926.             code = k5_get_ccache(kcontext,&ccache,op->cache);
  7927.             debug(F100,"krb5_init calling krb5_cc_initialize()","",0);
  7928.             code = krb5_cc_initialize (kcontext, ccache, me);
  7929.         } else
  7930.             code = KRB5_CC_BADNAME;
  7931.     }
  7932.     if (code) {
  7933.         com_err("krb5_kinit",code,"when initializing cache",op->cache);
  7934.         goto exit_k5_init;
  7935.     }
  7936.  
  7937.     debug(F100,"krb5_init calling krb5_cc_store_cred()","",0);
  7938.     code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
  7939.     if (code) {
  7940.         com_err("krb5_kinit",code,"while storing credentials");
  7941.         goto exit_k5_init;
  7942.     }
  7943.  
  7944. exit_k5_init:
  7945.     debug(F100,"krb5_init exit_k5_init","",0);
  7946.  
  7947. #ifndef HEIMDAL
  7948.     /* Free krb5_address structures if we created them */
  7949.     if ( addrs ) {
  7950.         for ( i=0;i<addr_count;i++ ) {
  7951.             if ( addrs[i] ) {
  7952.                 if ( addrs[i]->contents )
  7953.                     free(addrs[i]->contents);
  7954.                 free(addrs[i]);
  7955.             }
  7956.         }
  7957.     }
  7958. #endif /* HEIMDAL */
  7959.  
  7960.     /* my_creds is pointing at server */
  7961.     debug(F100,"krb5_init calling krb5_free_principal()","",0);
  7962.     krb5_free_principal(kcontext, server);
  7963.     debug(F100,"krb5_init calling krb5_cc_close()","",0);
  7964.     krb5_cc_close(kcontext,ccache);
  7965.     debug(F100,"krb5_init calling krb5_free_context()","",0);
  7966.     krb5_free_context(kcontext);
  7967.  
  7968.     krb5_errno = code;
  7969.     makestr(&krb5_errmsg,krb5_errno ? error_message(krb5_errno) : "OK");
  7970.  
  7971.     if ( init->getk4 && k4_init ) {
  7972.         int k4rc = ck_krb4_initTGT(op,k4_init);
  7973.         return (k4rc < 0 ? -1 : 0);
  7974.     }
  7975.  
  7976.     printf("Result from realm %s: %s\r\n",realm,
  7977.             code?error_message(code):"OK");
  7978.     return(code?-1:0);
  7979. }
  7980.  
  7981. #ifndef HEIMDAL
  7982. #define VALIDATE 0
  7983. #define RENEW 1
  7984.  
  7985. /* stripped down version of krb5_mk_req */
  7986. static krb5_error_code
  7987. #ifdef CK_ANSIC
  7988. krb5_validate_tgt( krb5_context context,
  7989.                    krb5_ccache ccache,
  7990.                    krb5_principal     server, /* tgtname */
  7991.                    krb5_data *outbuf )
  7992. #else
  7993. krb5_validate_tgt(context, ccache, server, outbuf)
  7994.      krb5_context context;
  7995.      krb5_ccache ccache;
  7996.      krb5_principal     server; /* tgtname */
  7997.      krb5_data *outbuf;
  7998. #endif
  7999. {
  8000.     return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
  8001. }
  8002.  
  8003. /* stripped down version of krb5_mk_req */
  8004. static krb5_error_code
  8005. #ifdef CK_ANSIC
  8006. krb5_renew_tgt(krb5_context context,
  8007.                 krb5_ccache ccache,
  8008.                 krb5_principal    server, /* tgtname */
  8009.                 krb5_data *outbuf)
  8010. #else
  8011. krb5_renew_tgt(context, ccache, server, outbuf)
  8012.      krb5_context context;
  8013.      krb5_ccache ccache;
  8014.      krb5_principal       server; /* tgtname */
  8015.      krb5_data *outbuf;
  8016. #endif
  8017. {
  8018.     return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
  8019. }
  8020.  
  8021.  
  8022. /* stripped down version of krb5_mk_req */
  8023. static krb5_error_code
  8024. #ifdef CK_ANSIC
  8025. krb5_tgt_gen(krb5_context context,
  8026.               krb5_ccache ccache,
  8027.               krb5_principal      server, /* tgtname */
  8028.               krb5_data *outbuf,
  8029.               int opt)
  8030. #else
  8031. krb5_tgt_gen(context, ccache, server, outbuf, opt)
  8032.      krb5_context context;
  8033.      krb5_ccache ccache;
  8034.      krb5_principal       server; /* tgtname */
  8035.      krb5_data *outbuf;
  8036.      int opt;
  8037. #endif
  8038. {
  8039.     krb5_error_code       retval;
  8040.     krb5_creds          * credsp;
  8041.     krb5_creds            creds;
  8042.  
  8043.     /* obtain ticket & session key */
  8044.     memset((char *)&creds, 0, sizeof(creds));
  8045.     if ((retval = krb5_copy_principal(context, server, &creds.server)))
  8046.         goto cleanup;
  8047.  
  8048.     if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
  8049.         goto cleanup_creds;
  8050.  
  8051.     if (opt == VALIDATE) {
  8052.         if ((retval = krb5_get_credentials_validate(context, 0,
  8053.                                                     ccache, &creds, &credsp)))
  8054.           goto cleanup_creds;
  8055.     } else {
  8056.         if ((retval = krb5_get_credentials_renew(context, 0,
  8057.                                                  ccache, &creds, &credsp)))
  8058.           goto cleanup_creds;
  8059.     }
  8060.  
  8061.     /* we don't actually need to do the mk_req, just get the creds. */
  8062. cleanup_creds:
  8063.     krb5_free_cred_contents(context, &creds);
  8064.  
  8065. cleanup:
  8066.  
  8067.     return retval;
  8068. }
  8069. #endif /* HEIMDAL */
  8070. #endif /* KINIT */
  8071. #ifdef KDESTROY
  8072. int
  8073. #ifdef CK_ANSIC
  8074. ck_krb5_destroy(struct krb_op_data * op)
  8075. #else
  8076. ck_krb5_destroy(op) struct krb_op_data * op;
  8077. #endif
  8078. {
  8079.     krb5_context kcontext;
  8080.     krb5_error_code retval;
  8081.     int c;
  8082.     krb5_ccache ccache = NULL;
  8083.     char *cache_name = NULL;
  8084.     int code;
  8085.     int errflg=0;
  8086.     int quiet = 0;
  8087.  
  8088.     if ( !ck_krb5_is_installed() )
  8089.         return(-1);
  8090.  
  8091.     code = krb5_init_context(&kcontext);
  8092.     if (code) {
  8093.         debug(F101,"ck_krb5_destroy while initializing krb5","",code);
  8094.         krb5_errno = code;
  8095.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8096.         return(-1);
  8097.     }
  8098.  
  8099.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  8100.     if (code != 0) {
  8101.         debug(F101,"ck_krb5_destroy while getting ccache",
  8102.                "",code);
  8103.         krb5_free_context(kcontext);
  8104.         krb5_errno = code;
  8105.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8106.         return(-1);
  8107.     }
  8108.  
  8109.     code = krb5_cc_destroy (kcontext, ccache);
  8110.     if (code != 0) {
  8111.         debug(F101,"ck_krb5_destroy while destroying cache","",code);
  8112.         if ( code == KRB5_FCC_NOFILE )
  8113.             printf("No ticket cache to destroy.\r\n");
  8114.         else
  8115.             printf("Ticket cache NOT destroyed!\r\n");
  8116.         krb5_cc_close(kcontext,ccache);
  8117.         krb5_free_context(kcontext);
  8118.         krb5_errno = code;
  8119.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8120.         return(-1);
  8121.     }
  8122.  
  8123.     printf("Tickets destroyed.\r\n");
  8124.     /* Do not call krb5_cc_close() because cache has been destroyed */
  8125.     krb5_free_context(kcontext);
  8126.     krb5_errno = 0;
  8127.     makestr(&krb5_errmsg,"OK");
  8128.     return (0);
  8129. }
  8130. #else /* KDESTROY */
  8131. #ifdef KRB5
  8132. int
  8133. #ifdef CK_ANSIC
  8134. ck_krb5_destroy(struct krb_op_data * op)
  8135. #else
  8136. ck_krb5_destroy(op) struct krb_op_data * op;
  8137. #endif
  8138. {
  8139.     printf("?Not implemented.\r\n");
  8140.     return(-1);
  8141. }
  8142. #endif /* KRB5 */
  8143. #endif /* KDESTROY */
  8144. #ifndef KLIST
  8145. #ifdef KRB5
  8146. int
  8147. #ifdef CK_ANSIC
  8148. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  8149. #else
  8150. ck_krb5_list_creds(op,lc)
  8151.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  8152. #endif
  8153. {
  8154.     printf("?Not implemented.\r\n");
  8155.     return(-1);
  8156. }
  8157. #endif /* KRB5 */
  8158. #else /* KLIST */
  8159. static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
  8160. static int show_etype = 0, show_addr = 0;
  8161. static char *defname;
  8162. static char *progname;
  8163. static krb5_int32 now;
  8164. static int timestamp_width;
  8165.  
  8166. _PROTOTYP(static char * etype_string, (krb5_enctype ));
  8167. _PROTOTYP(static void show_credential,(krb5_context,krb5_creds *));
  8168. _PROTOTYP(static int do_ccache, (krb5_context,char *));
  8169. _PROTOTYP(static int do_keytab, (krb5_context,char *));
  8170. _PROTOTYP(static void printtime, (time_t));
  8171. _PROTOTYP(static void fillit, (int, int));
  8172.  
  8173. #define DEFAULT 0
  8174. #define CCACHE 1
  8175. #define KEYTAB 2
  8176.  
  8177. int
  8178. #ifdef CK_ANSIC
  8179. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  8180. #else
  8181. ck_krb5_list_creds(op,lc)
  8182.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  8183. #endif
  8184. {
  8185.     krb5_context kcontext;
  8186.     krb5_error_code retval;
  8187.     int code;
  8188.     char *name = op->cache;
  8189.     int mode;
  8190.  
  8191.     if ( !ck_krb5_is_installed() )
  8192.         return(-1);
  8193.  
  8194.     code = krb5_init_context(&kcontext);
  8195.     if (code) {
  8196.         debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
  8197.         krb5_errno = code;
  8198.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8199.         return(-1);
  8200.     }
  8201.  
  8202.     name = op->cache;
  8203.     mode = DEFAULT;
  8204.     show_flags = 0;
  8205.     show_time = 0;
  8206.     status_only = 0;
  8207.     show_keys = 0;
  8208.     show_etype = 0;
  8209.     show_addr = 0;
  8210.  
  8211.     show_flags = lc->flags;
  8212.     show_etype = lc->encryption;
  8213.     show_addr  = lc->addr;
  8214.     show_time = 1;
  8215.     show_keys = 1;
  8216.     mode = CCACHE;
  8217.  
  8218.     if ((code = krb5_timeofday(kcontext, &now))) {
  8219.         if (!status_only)
  8220.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  8221.                    "",code);
  8222.         krb5_free_context(kcontext);
  8223.         krb5_errno = code;
  8224.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8225.         return(-1);
  8226.     }
  8227.     else {
  8228.         char tmp[BUFSIZ];
  8229.  
  8230.         if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
  8231.             !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
  8232.             timestamp_width = (int) strlen(tmp);
  8233.         else
  8234.             timestamp_width = 15;
  8235.     }
  8236.  
  8237.     if (mode == DEFAULT || mode == CCACHE)
  8238.          retval = do_ccache(kcontext,name);
  8239.     else
  8240.          retval = do_keytab(kcontext,name);
  8241.     krb5_free_context(kcontext);
  8242.     return(retval);
  8243. }
  8244.  
  8245. static int
  8246. #ifdef CK_ANSIC
  8247. do_keytab(krb5_context kcontext, char * name)
  8248. #else
  8249. do_keytab(kcontext,name) krb5_context kcontext; char * name;
  8250. #endif
  8251. {
  8252.     krb5_keytab kt;
  8253.     krb5_keytab_entry entry;
  8254.     krb5_kt_cursor cursor;
  8255.     char buf[BUFSIZ]; /* hopefully large enough for any type */
  8256.     char *pname;
  8257.     int code = 0;
  8258.  
  8259.     if (name == NULL) {
  8260.         if ((code = krb5_kt_default(kcontext, &kt))) {
  8261.             debug(F101,"ck_krb5_list_creds while getting default keytab",
  8262.                    "",code);
  8263.             krb5_errno = code;
  8264.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8265.             return(-1);
  8266.         }
  8267.     } else {
  8268.         if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
  8269.             debug(F111,"ck_krb5_list_creds while resolving keytab",
  8270.                      name,code);
  8271.             krb5_errno = code;
  8272.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8273.             return(-1);
  8274.         }
  8275.     }
  8276.  
  8277.     if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
  8278.         debug(F101,"ck_krb5_list_creds while getting keytab name",
  8279.                "",code);
  8280.         krb5_errno = code;
  8281.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8282.         return(-1);
  8283.     }
  8284.  
  8285.      printf("Keytab name: %s\r\n", buf);
  8286.  
  8287.      if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
  8288.          debug(F101,"ck_krb5_list_creds while starting keytab scan",
  8289.                 "",code);
  8290.          krb5_errno = code;
  8291.          makestr(&krb5_errmsg,error_message(krb5_errno));
  8292.          return(-1);
  8293.      }
  8294.  
  8295.      if (show_time) {
  8296.           printf("KVNO Timestamp");
  8297.           fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
  8298.           printf("Principal\r\n");
  8299.           printf("---- ");
  8300.           fillit(timestamp_width, (int) '-');
  8301.           printf(" ");
  8302.           fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
  8303.           printf("\r\n");
  8304.      } else {
  8305.           printf("KVNO Principal\r\n");
  8306.           printf(
  8307. "---- --------------------------------------------------------------------\
  8308. ------\r\n");
  8309.      }
  8310.  
  8311.     while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
  8312.         if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
  8313.             debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8314.                    "",code);
  8315.             krb5_errno = code;
  8316.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8317.             return(-1);
  8318.         }
  8319.         printf("%4d ", entry.vno);
  8320.         if (show_time) {
  8321.             printtime(entry.timestamp);
  8322.             printf(" ");
  8323.         }
  8324.         printf("%s", pname);
  8325.         if (show_etype)
  8326.             printf(" (%s) " ,
  8327. #ifdef HEIMDAL
  8328.                     etype_string(entry.key.keytype)
  8329. #else /* HEIMDAL */
  8330.                     etype_string(entry.key.enctype)
  8331. #endif /* HEIMDAL */
  8332.                     );
  8333.         if (show_keys) {
  8334.             printf(" (0x");
  8335.             {
  8336.                 int i;
  8337.                 for (i = 0; i < entry.key.length; i++)
  8338.                     printf("%02x",
  8339. #ifdef HEIMDAL
  8340.                             entry.key.keyvalue[i]
  8341. #else /* HEIMDAL */
  8342.                             entry.key.contents[i]
  8343. #endif /* HEIMDAL */
  8344.                             );
  8345.             }
  8346.             printf(")");
  8347.         }
  8348.         printf("\r\n");
  8349.         krb5_free_unparsed_name(kcontext,pname);
  8350.     }
  8351.     if (code && code != KRB5_KT_END) {
  8352.         debug(F101,"ck_krb5_list_creds while scanning keytab",
  8353.                "",code);
  8354.         krb5_errno = code;
  8355.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8356.         return(-1);
  8357.     }
  8358.     if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
  8359.         debug(F101,"ck_krb5_list_creds while ending keytab scan",
  8360.                "",code);
  8361.         krb5_errno = code;
  8362.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8363.         return(-1);
  8364.     }
  8365.     krb5_errno = 0;
  8366.     makestr(&krb5_errmsg,"OK");
  8367.     return(0);
  8368. }
  8369.  
  8370. static int
  8371. #ifdef CK_ANSIC
  8372. do_ccache(krb5_context kcontext, char * cc_name)
  8373. #else
  8374. do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
  8375. #endif
  8376. {
  8377.     krb5_ccache cache = NULL;
  8378.     krb5_cc_cursor cur;
  8379.     krb5_creds creds;
  8380.     krb5_principal princ=NULL;
  8381.     krb5_flags flags=0;
  8382.     krb5_error_code code = 0;
  8383.     int exit_status = 0;
  8384.  
  8385.     if (status_only)
  8386.         /* exit_status is set back to 0 if a valid tgt is found */
  8387.         exit_status = 1;
  8388.  
  8389.     code = k5_get_ccache(kcontext,&cache,cc_name);
  8390.     if (code != 0) {
  8391.         debug(F111,"do_ccache while getting ccache",
  8392.                error_message(code),code);
  8393.         krb5_errno = code;
  8394.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8395.         return(-1);
  8396.     }
  8397.  
  8398.     flags = 0;                          /* turns off OPENCLOSE mode */
  8399.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8400.         if (code == ENOENT) {
  8401.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  8402.                    krb5_cc_get_name(kcontext, cache),code);
  8403.         } else {
  8404.             debug(F111,
  8405.                  "ck_krb5_list_creds while setting cache flags (ticket cache)",
  8406.                   krb5_cc_get_name(kcontext, cache),code);
  8407.         }
  8408.         printf("No ticket File.\r\n");
  8409.         krb5_errno = code;
  8410.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8411.         krb5_cc_close(kcontext,cache);
  8412.         return(-1);
  8413.     }
  8414.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  8415.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  8416.                "",code);
  8417.         krb5_errno = code;
  8418.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8419.         krb5_cc_close(kcontext,cache);
  8420.         return(-1);
  8421.     }
  8422.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  8423.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8424.                "",code);
  8425.         krb5_errno = code;
  8426.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8427.         krb5_cc_close(kcontext,cache);
  8428.         return(-1);
  8429.     }
  8430.     if (!status_only) {
  8431.         printf("Ticket cache:      %s:%s\r\nDefault principal: %s\r\n\r\n",
  8432.                 krb5_cc_get_type(kcontext, cache),
  8433.                 krb5_cc_get_name(kcontext, cache), defname);
  8434.         printf("Valid starting");
  8435.         fillit(timestamp_width - sizeof("Valid starting") + 3,
  8436.                (int) ' ');
  8437.         printf("Expires");
  8438.         fillit(timestamp_width - sizeof("Expires") + 3,
  8439.                (int) ' ');
  8440.         printf("Service principal\r\n");
  8441.     }
  8442.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  8443.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  8444.                "",code);
  8445.         krb5_errno = code;
  8446.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8447.         krb5_cc_close(kcontext,cache);
  8448.         return(-1);
  8449.     }
  8450.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  8451.         if (status_only) {
  8452.             if (exit_status && creds.server->length == 2 &&
  8453.                 strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
  8454.                 strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
  8455.                 strcmp((char *)creds.server->data[1].data,
  8456.                        princ->realm.data) == 0 &&
  8457.                 creds.times.endtime > now)
  8458.                 exit_status = 0;
  8459.         } else {
  8460.             show_credential(kcontext, &creds);
  8461.         }
  8462.         krb5_free_cred_contents(kcontext, &creds);
  8463.     }
  8464.     printf("\r\n");
  8465.     if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
  8466.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  8467.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  8468.                    "",code);
  8469.             krb5_errno = code;
  8470.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8471.             krb5_cc_close(kcontext,cache);
  8472.             return(-1);
  8473.         }
  8474.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  8475.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8476.             debug(F101,"ck_krb5_list_creds while closing ccache",
  8477.                    "",code);
  8478.             krb5_errno = code;
  8479.             makestr(&krb5_errmsg,error_message(krb5_errno));
  8480.             krb5_cc_close(kcontext,cache);
  8481.             return(-1);
  8482.         }
  8483.         krb5_errno = 0;
  8484.         makestr(&krb5_errmsg,"OK");
  8485.         krb5_cc_close(kcontext,cache);
  8486.         return(0);
  8487.     } else {
  8488.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  8489.         krb5_errno = code;
  8490.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8491.         krb5_cc_close(kcontext,cache);
  8492.         return(-1);
  8493.     }
  8494.     krb5_errno = 0;
  8495.     makestr(&krb5_errmsg,"OK");
  8496.     krb5_cc_close(kcontext,cache);
  8497.     return(0);
  8498. }
  8499.  
  8500. static char *
  8501. #ifdef CK_ANSIC
  8502. #ifdef HEIMDAL
  8503. etype_string(krb5_keytype enctype)
  8504. #else /* HEIMDAL */
  8505. etype_string(krb5_enctype enctype)
  8506. #endif /* HEIMDAL */
  8507. #else
  8508. #ifdef HEIMDAL
  8509. etype_string(enctype) krb5_keytype enctype;
  8510. #else /* HEIMDAL */
  8511. etype_string(enctype) krb5_enctype enctype;
  8512. #endif /* HEIMDAL */
  8513. #endif
  8514. {
  8515.     static char buf[12];
  8516.  
  8517.     switch (enctype) {
  8518.     case ENCTYPE_NULL:
  8519.         return "NULL";
  8520.     case ENCTYPE_DES_CBC_CRC:
  8521.         return "DES-CBC-CRC";
  8522.     case ENCTYPE_DES_CBC_MD4:
  8523.         return "DES-CBC-MD4";
  8524.     case ENCTYPE_DES_CBC_MD5:
  8525.         return "DES-CBC-MD5";
  8526.     case ENCTYPE_DES_CBC_RAW:
  8527.         return "DES-CBC-RAW";
  8528.     case ENCTYPE_DES3_CBC_SHA:
  8529.         return "DES3-CBC-SHA";
  8530.     case ENCTYPE_DES3_CBC_RAW:
  8531.         return "DES3-CBC-RAW";
  8532.     case ENCTYPE_DES_HMAC_SHA1:
  8533.         return "DES-HMAC-SHA1";
  8534.     case ENCTYPE_DES3_CBC_SHA1:
  8535.         return "DES3-CBC-SHA1";
  8536.     case ENCTYPE_UNKNOWN:
  8537.         return "UNKNOWN";
  8538.     case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
  8539.         return "LOCAL-DES3-HMAC-SHA1";
  8540.     default:
  8541.         ckmakmsg(buf, sizeof(buf),"etype ", ckitoa(enctype),NULL,NULL);
  8542.         return buf;
  8543.         break;
  8544.     }
  8545. }
  8546.  
  8547. static char *
  8548. #ifdef CK_ANSIC
  8549. flags_string(register krb5_creds *cred)
  8550. #else
  8551. flags_string(cred) register krb5_creds *cred;
  8552. #endif
  8553. {
  8554.     static char buf[32];
  8555.     int i = 0;
  8556.  
  8557.     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
  8558.         buf[i++] = 'F';
  8559.     if (cred->ticket_flags & TKT_FLG_FORWARDED)
  8560.         buf[i++] = 'f';
  8561.     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
  8562.         buf[i++] = 'P';
  8563.     if (cred->ticket_flags & TKT_FLG_PROXY)
  8564.         buf[i++] = 'p';
  8565.     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
  8566.         buf[i++] = 'D';
  8567.     if (cred->ticket_flags & TKT_FLG_POSTDATED)
  8568.         buf[i++] = 'd';
  8569.     if (cred->ticket_flags & TKT_FLG_INVALID)
  8570.         buf[i++] = 'i';
  8571.     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
  8572.         buf[i++] = 'R';
  8573.     if (cred->ticket_flags & TKT_FLG_INITIAL)
  8574.         buf[i++] = 'I';
  8575.     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
  8576.         buf[i++] = 'H';
  8577.     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
  8578.         buf[i++] = 'A';
  8579.     buf[i] = '\0';
  8580.     return(buf);
  8581. }
  8582.  
  8583. static char   *
  8584. #ifdef CK_ANSIC
  8585. short_date(long   *dp)
  8586. #else
  8587. short_date(dp) long   *dp;
  8588. #endif
  8589. {
  8590.     register char *cp;
  8591. #ifndef ctime
  8592.     extern char *ctime();
  8593. #endif /* ctime */
  8594.     cp = ctime(dp) + 4;
  8595.     cp[15] = '\0';
  8596.     return (cp);
  8597. }
  8598.  
  8599.  
  8600. static VOID
  8601. #ifdef CK_ANSIC
  8602. printtime(time_t tv)
  8603. #else
  8604. printtime(tv) time_t tv;
  8605. #endif
  8606. {
  8607.     char timestring[BUFSIZ];
  8608.     char format[12];
  8609.     char fill;
  8610.  
  8611.     fill = ' ';
  8612.     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
  8613.     if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
  8614.                                      timestring,
  8615.                                      timestamp_width+1,
  8616.                                      &fill)) {
  8617.         printf(format,timestring);
  8618.     }
  8619.     else {
  8620.         printf(format,short_date(&tv));
  8621.     }
  8622.  
  8623. }
  8624.  
  8625. static void
  8626. #ifdef CK_ANSIC
  8627. one_addr(krb5_address *a)
  8628. #else
  8629. one_addr(a) krb5_address *a;
  8630. #endif
  8631. {
  8632.     struct hostent *h;
  8633.     extern tcp_rdns;
  8634.  
  8635.     if ((a->addrtype == ADDRTYPE_INET) &&
  8636.         (a->length == 4)) {
  8637.         if (tcp_rdns != SET_OFF) {
  8638.             h = gethostbyaddr(a->contents, 4, AF_INET);
  8639.             if (h) {
  8640. #ifdef HADDRLIST
  8641.                 h = ck_copyhostent(h);
  8642. #endif /* HADDRLIST */
  8643.                 printf("%s (%d.%d.%d.%d)", h->h_name,
  8644.                         a->contents[0], a->contents[1],
  8645.                         a->contents[2], a->contents[3]);
  8646.             }
  8647.         }
  8648.         if (tcp_rdns == SET_OFF || !h) {
  8649.             printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
  8650.                    a->contents[2], a->contents[3]);
  8651.         }
  8652.     } else {
  8653.         printf("unknown addr type %d", a->addrtype);
  8654.     }
  8655. }
  8656.  
  8657. static VOID
  8658. #ifdef CK_ANSIC
  8659. show_credential(krb5_context kcontext, register krb5_creds * cred)
  8660. #else
  8661. show_credential(kcontext, cred)
  8662.     krb5_context          kcontext;
  8663.     register krb5_creds * cred;
  8664. #endif
  8665. {
  8666.     krb5_error_code retval=0;
  8667.     krb5_ticket *tkt=NULL;
  8668.     char *name=NULL, *sname=NULL, *flags=NULL;
  8669.     int extra_field = 0;
  8670.  
  8671.     retval = krb5_unparse_name(kcontext, cred->client, &name);
  8672.     if (retval) {
  8673.         debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
  8674.         krb5_errno = retval;
  8675.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8676.         return;
  8677.     }
  8678.     retval = krb5_unparse_name(kcontext, cred->server, &sname);
  8679.     if (retval) {
  8680.         debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
  8681.         free(name);
  8682.         krb5_errno = retval;
  8683.         makestr(&krb5_errmsg,error_message(krb5_errno));
  8684.         return;
  8685.     }
  8686.     if (!cred->times.starttime)
  8687.         cred->times.starttime = cred->times.authtime;
  8688.  
  8689.     printtime(cred->times.starttime);
  8690.     printf("  ");
  8691.  
  8692.     if ( time(0) < cred->times.endtime )
  8693.         printtime(cred->times.endtime);
  8694.     else
  8695.         printf("** expired ** ");
  8696.  
  8697.     printf("  %s\r\n", sname);
  8698.  
  8699.     if (strcmp(name, defname)) {
  8700.         printf("   for client %s", name);
  8701.         extra_field++;
  8702.     }
  8703.  
  8704.     if (cred->times.renew_till) {
  8705.         if (!extra_field)
  8706.             printf("   ");
  8707.         else
  8708.             printf(", ");
  8709.         printf("renew until ");
  8710.         printtime(cred->times.renew_till);
  8711.         extra_field += 2;
  8712.     }
  8713.  
  8714.     if (extra_field > 3) {
  8715.         printf("\r\n");
  8716.         extra_field = 0;
  8717.     }
  8718.  
  8719.     if (show_flags) {
  8720.         flags = flags_string(cred);
  8721.         if (flags && *flags) {
  8722.             if (!extra_field)
  8723.                 printf("   ");
  8724.             else
  8725.                 printf(", ");
  8726.             printf("Flags: %s", flags);
  8727.             extra_field++;
  8728.         }
  8729.     }
  8730.  
  8731.     if (extra_field > 2) {
  8732.         printf("\r\n");
  8733.         extra_field = 0;
  8734.     }
  8735.  
  8736.     if (show_etype) {
  8737.         retval = decode_krb5_ticket(&cred->ticket, &tkt);
  8738.         if (!extra_field)
  8739.             printf("   ");
  8740.         else
  8741.             printf(", ");
  8742. #ifdef HEIMDAL
  8743.         printf("Etype (skey, tkt): %s, %s ",
  8744.                etype_string(cred->session.keytype),
  8745.                etype_string(tkt->enc_part.keytype));
  8746. #else /* HEIMDAL */
  8747.         printf("Etype (skey, tkt): %s, %s ",
  8748.                etype_string(cred->keyblock.enctype),
  8749.                etype_string(tkt->enc_part.enctype));
  8750. #endif /* HEIMDAL */
  8751.         krb5_free_ticket(kcontext, tkt);
  8752.         extra_field++;
  8753.     }
  8754.  
  8755.     /* if any additional info was printed, extra_field is non-zero */
  8756.     if (extra_field)
  8757.         printf("\r\n");
  8758.  
  8759.     if ( show_addr ) {
  8760.         if (!cred->addresses || !cred->addresses[0]) {
  8761.             printf("\tAddresses: (none)\r\n");
  8762.         } else {
  8763.             int i;
  8764.             for (i=0; cred->addresses[i]; i++) {
  8765.                 if (i)
  8766.                     printf("              ");
  8767.                 else
  8768.                     printf("   Addresses: ");
  8769.                 one_addr(cred->addresses[i]);
  8770.                 printf("\r\n");
  8771.             }
  8772.         }
  8773.     }
  8774.  
  8775.     krb5_free_unparsed_name(kcontext,name);
  8776.     krb5_free_unparsed_name(kcontext,sname);
  8777.  
  8778.     krb5_errno = 0;
  8779.     makestr(&krb5_errmsg,"OK");
  8780. }
  8781.  
  8782. static VOID
  8783. #ifdef CK_ANSIC
  8784. fillit(int num, int c)
  8785. #else
  8786. fillit(num, c) int num; int c;
  8787. #endif
  8788. {
  8789.     int i;
  8790.  
  8791.     for (i=0; i<num; i++)
  8792.         printf("%c",c);
  8793. }
  8794. #endif /* KLIST */
  8795. #endif /* KRB5 */
  8796.  
  8797. #ifdef KRB4
  8798. #define KDEBUG 1
  8799. int k4debug = 0;                /* Kerberos 4 runtime debugging */
  8800.  
  8801. #ifdef KINIT
  8802. #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
  8803.  
  8804. #ifdef SNK4
  8805. /* SNK4 is a hardware authentication system used to pre-authenticate    */
  8806. /* a ticket getting ticket.  We do not support this code at the present */
  8807. /* time in Kermit.                                                      */
  8808. void
  8809. get_input(s, size, stream)
  8810. char *s;
  8811. int size;
  8812. FILE *stream;
  8813. {
  8814.     char *p;
  8815.  
  8816.     if (fgets(s, size, stream) == NULL)
  8817.         exit(1);
  8818.     if ( (p = strchr(s, '\n')) != NULL)
  8819.         *p = '\0';
  8820. }
  8821. #endif /* SNK4 */
  8822.  
  8823. #ifdef COMMENT
  8824. static char
  8825. #ifdef CK_ANSIC
  8826. hex_scan_nybble(char c)
  8827. #else
  8828. hex_scan_nybble(c) char c;
  8829. #endif
  8830. {
  8831.     if (c >= '0' && c <= '9')
  8832.         return c - '0';
  8833.     if (c >= 'A' && c <= 'F')
  8834.         return c - 'A' + 10;
  8835.     if (c >= 'a' && c <= 'f')
  8836.         return c - 'a' + 10;
  8837.     return -1;
  8838. }
  8839.  
  8840. /* returns: NULL for ok, pointer to error string for bad input */
  8841. static char*
  8842. #ifdef CK_ANSIC
  8843. hex_scan_four_bytes(char *out, char *in)
  8844. #else
  8845. hex_scan_four_bytes(out, in) char *out; char *in;
  8846. #endif
  8847. {
  8848.     int i;
  8849.     int c;
  8850.     char c1;
  8851.     for (i=0; i<8; i++) {
  8852.         if(!in[i])
  8853.             return "not enough input";
  8854.         c = hex_scan_nybble(in[i]);
  8855.         if(c<0)
  8856.             return "invalid digit";
  8857.         c1 = c;
  8858.         i++;
  8859.         if(!in[i])
  8860.             return "not enough input";
  8861.         c = hex_scan_nybble(in[i]);
  8862.         if(c<0)
  8863.             return "invalid digit";
  8864.         *out++ = (c1 << 4) + c;
  8865.     }
  8866.     switch(in[i]) {
  8867.     case 0:
  8868.     case '\r':
  8869.     case '\n':
  8870.         return NULL;
  8871.     default:
  8872.         return "extra characters at end of input";
  8873.     }
  8874. }
  8875. #endif /* COMMENT */
  8876.  
  8877. /* ck_krb4_initTGT() returns 0 on success */
  8878. int
  8879. #ifdef CK_ANSIC
  8880. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  8881. #else
  8882. ck_krb4_initTGT(op,init)
  8883.     struct krb_op_data * op, struct krb4_init_data * init
  8884. #endif
  8885. {
  8886.     char    aname[ANAME_SZ+1];
  8887.     char    inst[INST_SZ+1];
  8888.     char    realm[REALM_SZ+1];
  8889.     char    *password=NULL;
  8890.     char    passwd[80]="";
  8891.     char    *username = NULL;
  8892.     char    *usernameptr=NULL;
  8893.     int     iflag,      /* Instance */
  8894.             rflag,      /* Realm */
  8895.             vflag,      /* Verbose */
  8896.             lflag,      /* Lifetime */
  8897.             pflag,      /* Preauth */
  8898.             lifetime=KRB_DEFAULT_LIFE,   /* Life Time */
  8899.             k_errno;
  8900.     register char *cp;
  8901.     register i;
  8902.  
  8903.     if ( !ck_krb4_is_installed() )
  8904.         return(-1);
  8905.  
  8906.     *inst = *realm = '\0';
  8907.     iflag = rflag = vflag = lflag = pflag = 0;
  8908.  
  8909.     vflag = init->verbose;
  8910.     pflag = init->preauth;
  8911.  
  8912.     if ( init->lifetime ) {
  8913.         lifetime = init->lifetime<5?1:init->lifetime/5;
  8914.         if ( lifetime > 255 ) lifetime = 255;
  8915.     }
  8916.     else
  8917.         lifetime = KRB_DEFAULT_LIFE;
  8918.  
  8919.     username = init->principal;
  8920.  
  8921.     if (username && username[0] &&
  8922.         (k_errno = kname_parse(aname, inst, realm, username))
  8923.         != AUTH_SUCCESS) {
  8924.         krb4_errno = k_errno;
  8925.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  8926.         printf("%s\r\n", krb_get_err_text_entry(k_errno));
  8927.         iflag = rflag = 1;
  8928.         username = NULL;
  8929.     }
  8930.  
  8931.     if ( init->realm ) {
  8932.         ckstrncpy(realm,init->realm,REALM_SZ);
  8933.     }
  8934.  
  8935.     if ( init->instance ) {
  8936.         ckstrncpy(inst,init->instance, INST_SZ);
  8937.     }
  8938.  
  8939. #ifdef COMMENT
  8940.     if ( vflag )
  8941.         printf("Kerberos IV initialization\r\n");
  8942. #endif /* COMMENT */
  8943.  
  8944.     if (!username || !username[0]) {
  8945.         debug(F100,"ck_krb4_initTGT no username specified","",0);
  8946.         printf("?Invalid principal specified.\r\n");
  8947.         krb4_errno = -1;
  8948.         makestr(&krb4_errmsg,"No principal specified");
  8949.         return(-1);
  8950.     }
  8951.     if (!*realm) {
  8952.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
  8953.     }
  8954.  
  8955.     if ( init->password )
  8956.         password = init->password;
  8957.     else {
  8958.         char prmpt[80];
  8959.         ckmakxmsg(prmpt,sizeof(prmpt),
  8960.                   "Kerberos 4 Password for ",username,"@",realm,": ",
  8961.                    NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  8962.         readpass(prmpt,passwd,80);
  8963.         password = passwd;
  8964.     }
  8965.  
  8966.     if (pflag) {
  8967.         k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
  8968.                                              "krbtgt", realm,
  8969.                                              lifetime,
  8970.                                              password);
  8971.         if (k_errno == -1) {    /* preauth method not available */
  8972.             k_errno = krb_get_pw_in_tkt(aname,
  8973.                                          inst, realm,
  8974.                                          "krbtgt", realm,
  8975.                                          lifetime,
  8976.                                          password);
  8977.         }
  8978.     } else {
  8979.         k_errno = krb_get_pw_in_tkt(aname,
  8980.                                      inst, realm,
  8981.                                      "krbtgt", realm,
  8982.                                      lifetime,
  8983.                                      password);
  8984.     }
  8985.  
  8986.     memset(passwd,0,sizeof(passwd));
  8987.     if (k_errno) {
  8988.         printf("%s for principal %s%s%s@%s\r\n",
  8989.                 krb_get_err_text_entry(k_errno), aname,
  8990.                 inst[0]?".":"", inst, realm);
  8991.         krb4_errno = k_errno;
  8992.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  8993.         return(-1);
  8994.     } else if (vflag) {
  8995.         printf("Result from realm %s: ", realm);
  8996.         printf("%s\r\n", krb_get_err_text_entry(k_errno));
  8997.     }
  8998.     krb4_errno = k_errno;
  8999.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9000.     return(0);
  9001. }
  9002. #endif /* KINIT */
  9003. #ifdef KDESTROY
  9004. int
  9005. #ifdef CK_ANSIC
  9006. ck_krb4_destroy(struct krb_op_data * op)
  9007. #else
  9008. ck_krb4_destroy(op) struct krb_op_data * op;
  9009. #endif
  9010. {
  9011.     int k_errno=0;
  9012.  
  9013.     if ( !ck_krb4_is_installed() )
  9014.         return(-1);
  9015.  
  9016.     k_errno = dest_tkt();
  9017.  
  9018.     krb4_errno = k_errno;
  9019.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9020.  
  9021.     if (k_errno == 0)
  9022.         printf("Tickets destroyed.\r\n");
  9023.     else if (k_errno == RET_TKFIL)
  9024.         printf("No tickets to destroy.\r\n");
  9025.     else {
  9026.         printf("Tickets MAY NOT be destroyed.\r\n");
  9027.         return(-1);
  9028.     }
  9029.     return(0);
  9030. }
  9031. #endif /* KDESTROY */
  9032. #ifdef KLIST
  9033. _PROTOTYP(static int display_tktfile,(char *, int, int, int));
  9034.  
  9035. int
  9036. #ifdef CK_ANSIC
  9037. ck_krb4_list_creds(struct krb_op_data * op)
  9038. #else
  9039. ck_krb4_list_creds(op) struct krb_op_data * op;
  9040. #endif
  9041. {
  9042.     int     long_form = 1;
  9043.     int     tgt_test = 0;
  9044.     int     do_srvtab = 0;
  9045.     int     show_kvnos = 0;
  9046.     char   *tkt_file = NULL;
  9047.  
  9048.     if ( !ck_krb4_is_installed() )
  9049.         return(-1);
  9050.  
  9051.     if ( op->cache )
  9052.         tkt_file = op->cache;
  9053.  
  9054.     if ( k4debug ) {
  9055.         show_kvnos = 1;
  9056.     }
  9057.  
  9058.     if (do_srvtab)
  9059.         return(display_srvtab(tkt_file));
  9060.     else
  9061.         return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
  9062. }
  9063.  
  9064. #ifndef KRB5
  9065. static int timestamp_width=0;
  9066.  
  9067. static char   *
  9068. #ifdef CK_ANSIC
  9069. short_date(long   *dp)
  9070. #else
  9071. short_date(dp) long   *dp;
  9072. #endif
  9073. {
  9074.     register char *cp;
  9075.     extern char *ctime();
  9076.     cp = ctime(dp) + 4;
  9077.     cp[15] = '\0';
  9078.     return (cp);
  9079. }
  9080.  
  9081.  
  9082. static VOID
  9083. #ifdef CK_ANSIC
  9084. printtime(time_t tv)
  9085. #else
  9086. printtime(tv) time_t tv;
  9087. #endif
  9088. {
  9089.     char timestring[BUFSIZ];
  9090.     char format[12];
  9091.     char fill;
  9092.  
  9093.     fill = ' ';
  9094.     sprintf(format,"%%-%ds",timestamp_width);   /* safe */
  9095.     printf(format,short_date(&tv));
  9096. }
  9097. #endif /* KRB5 */
  9098.  
  9099. static int
  9100. #ifdef CK_ANSIC
  9101. display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
  9102. #else
  9103. display_tktfile(file,tgt_test,long_form,show_kvnos)
  9104.     char *file; int tgt_test; int long_form; int show_kvnos;
  9105. #endif
  9106. {
  9107.     char    pname[ANAME_SZ];
  9108.     char    pinst[INST_SZ];
  9109.     char    prealm[REALM_SZ];
  9110.     char    buf1[20], buf2[20];
  9111.     int     k_errno;
  9112. #ifdef OS2
  9113.     LEASH_CREDENTIALS creds;
  9114. #else /* OS2 */
  9115.     CREDENTIALS creds;
  9116. #endif /* OS2 */
  9117.     int     header = 1;
  9118.  
  9119.     file = tkt_string();
  9120.  
  9121.     if (long_form) {
  9122.         printf("Ticket cache:      %s\r\n", file);
  9123.     }
  9124.  
  9125.     /*
  9126.      * Since krb_get_tf_realm will return a ticket_file error,
  9127.      * we will call tf_init and tf_close first to filter out
  9128.      * things like no ticket file.  Otherwise, the error that
  9129.      * the user would see would be
  9130.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9131.      * instead of
  9132.      * klist: No ticket file (tf_util)
  9133.      */
  9134.  
  9135.     /* Open ticket file */
  9136.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9137.         if (!tgt_test)
  9138.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9139.         krb4_errno = k_errno;
  9140.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9141.         return(-1);
  9142.     }
  9143.  
  9144.  
  9145.     /* Close ticket file */
  9146.     (void) tf_close();
  9147.  
  9148.     /*
  9149.      * We must find the realm of the ticket file here before calling
  9150.      * tf_init because since the realm of the ticket file is not
  9151.      * really stored in the principal section of the file, the
  9152.      * routine we use must itself call tf_init and tf_close.
  9153.      */
  9154.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9155.         if (!tgt_test)
  9156.             printf("can't find realm of ticket file: %s\r\n",
  9157.                     krb_get_err_text_entry (k_errno));
  9158.         krb4_errno = k_errno;
  9159.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9160.         return(-1);
  9161.     }
  9162.  
  9163.     /* Open ticket file */
  9164.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9165.         if (!tgt_test)
  9166.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9167.         krb4_errno = k_errno;
  9168.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9169.         return(-1);
  9170.     }
  9171.     /* Get principal name and instance */
  9172.     if ((k_errno = tf_get_pname(pname)) ||
  9173.          (k_errno = tf_get_pinst(pinst))) {
  9174.         (void) tf_close();
  9175.         if (!tgt_test)
  9176.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  9177.         krb4_errno = k_errno;
  9178.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9179.         return(-1);
  9180.     }
  9181.  
  9182.     /*
  9183.      * You may think that this is the obvious place to get the
  9184.      * realm of the ticket file, but it can't be done here as the
  9185.      * routine to do this must open the ticket file.  This is why
  9186.      * it was done before tf_init.
  9187.      */
  9188.  
  9189.     if (!tgt_test && long_form)
  9190.         printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
  9191.                (pinst[0] ? "." : ""), pinst,
  9192.                (prealm[0] ? "@" : ""), prealm);
  9193.  
  9194.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9195.         if (!tgt_test && long_form && header) {
  9196.             printf("%-17s  %-17s  %s\r\n",
  9197.                    "Valid starting", "Expires", "Service principal");
  9198.             header = 0;
  9199.         }
  9200.         if (tgt_test) {
  9201.             creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  9202.             if (!strcmp(creds.service, "krbtgt") &&
  9203.                 !strcmp(creds.instance, prealm)) {
  9204.                 krb4_errno = k_errno;
  9205.                 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9206.  
  9207.                 (void) tf_close();
  9208.                 if (time(0) < creds.issue_date) {
  9209.                     return(0);          /* tgt hasn't expired */
  9210.                 } else {
  9211.                     return(-1);         /* has expired */
  9212.                 }
  9213.             }
  9214.             continue;                   /* not a tgt */
  9215.         }
  9216.         if (long_form) {
  9217.             timestamp_width = 17;       /* for k5 display function */
  9218.                                         /* if available            */
  9219.             printtime(creds.issue_date);
  9220.             printf("  ");
  9221.             creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  9222.             if ( time(0) < creds.issue_date )
  9223.                 printtime(creds.issue_date);
  9224.             else
  9225.                 printf("*** expired ***  ");
  9226.             printf("  ");
  9227.         }
  9228.         if (show_kvnos)
  9229.           printf("%s%s%s%s%s (%d)\r\n",
  9230.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9231.                  (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
  9232.         else
  9233.           printf("%s%s%s%s%s\r\n",
  9234.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9235.                  (creds.realm[0] ? "@" : ""), creds.realm);
  9236.  
  9237. #ifdef OS2
  9238.         if ( creds.address[0] )
  9239.             printf("   Address: %s\r\n",creds.address);
  9240. #endif /* OS2 */
  9241.     }
  9242.  
  9243.     (void) tf_close();
  9244.  
  9245.     if (tgt_test) {
  9246.         return(-1);
  9247.     }/* no tgt found */
  9248.     if (header && long_form && k_errno == EOF) {
  9249.         printf("No tickets in file.\r\n");
  9250.     }
  9251.     krb4_errno = k_errno;
  9252.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  9253.     return(0);
  9254. }
  9255.  
  9256. #ifdef COMMENT
  9257. /* Just so we remember what the command line interface looked like */
  9258. usage()
  9259. {
  9260.     printf(
  9261.         "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
  9262.     return(-1);
  9263. }
  9264. #endif /* COMMENT */
  9265.  
  9266. /* adapted from getst() in librkb */
  9267. /*
  9268.  * ok_getst() takes a file descriptor, a string and a count.  It reads
  9269.  * from the file until either it has read "count" characters, or until
  9270.  * it reads a null byte.  When finished, what has been read exists in
  9271.  * the given string "s".  If "count" characters were actually read, the
  9272.  * last is changed to a null, so the returned string is always null-
  9273.  * terminated.  ok_getst() returns the number of characters read, including
  9274.  * the null terminator.
  9275.  *
  9276.  * If there is a read error, it returns -1 (like the read(2) system call)
  9277.  */
  9278.  
  9279. static int
  9280. #ifdef CK_ANSIC
  9281. ok_getst(int fd, register char *s, int n)
  9282. #else
  9283. ok_getst(fd, s, n) int fd; register char *s; int n;
  9284. #endif
  9285. {
  9286.     register int count = n;
  9287.     int err;
  9288.     while ((err = read(fd, s, 1)) > 0 && --count)
  9289.         if (*s++ == '\0')
  9290.             return (n - count);
  9291.     if (err < 0)
  9292.         return(-1);
  9293.     *s = '\0';
  9294.     return (n - count);
  9295. }
  9296.  
  9297. int
  9298. #ifdef CK_ANSIC
  9299. display_srvtab(char *file)
  9300. #else
  9301. display_srvtab(file) char *file;
  9302. #endif
  9303. {
  9304.     int stab;
  9305.     char serv[SNAME_SZ];
  9306.     char inst[INST_SZ];
  9307.     char rlm[REALM_SZ];
  9308.     unsigned char key[8];
  9309.     unsigned char vno;
  9310.     int count;
  9311.  
  9312.     printf("Server key file:   %s\r\n", file);
  9313. #ifdef NT
  9314. #ifndef O_RDONLY
  9315. #define O_RDONLY _O_RDONLY
  9316. #endif /* O_RDONLY */
  9317. #endif /* NT */
  9318.  
  9319.     if ((stab = open(file, O_RDONLY, 0400)) < 0) {
  9320.         perror(file);
  9321.         return(-1);
  9322.     }
  9323.     printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
  9324.            "Key Version");
  9325.     printf("------------------------------------------------------\r\n");
  9326.  
  9327.     /* argh. getst doesn't return error codes, it silently fails */
  9328.     while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
  9329.            && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
  9330.            && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
  9331.         if (((count = read(stab,(char *) &vno,1)) != 1) ||
  9332.              ((count = read(stab,(char *) key,8)) != 8)) {
  9333.             if (count < 0)
  9334.                 perror("reading from key file");
  9335.             else
  9336.                 printf("key file truncated\r\n");
  9337.             return(-1);
  9338.         }
  9339.         printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
  9340.     }
  9341.     if (count < 0)
  9342.         perror(file);
  9343.     (void) close(stab);
  9344.     return(0);
  9345. }
  9346. #endif /* KLIST */
  9347. #else /* KRB4 */
  9348. int
  9349. ck_krb4_autoget_TGT(char * dummy)
  9350. {
  9351.     return(-1);
  9352. }
  9353. #ifdef CK_KERBEROS
  9354. int
  9355. #ifdef CK_ANSIC
  9356. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  9357. #else
  9358. ck_krb4_initTGT(op,init)
  9359.     struct krb_op_data * op, struct krb4_init_data * init
  9360. #endif
  9361. {
  9362.     return(-1);
  9363. }
  9364.  
  9365. #ifdef CK_ANSIC
  9366. ck_krb4_destroy(struct krb_op_data * op)
  9367. #else
  9368. ck_krb4_destroy(op) struct krb_op_data * op;
  9369. #endif
  9370. {
  9371.     return(-1);
  9372. }
  9373. int
  9374. #ifdef CK_ANSIC
  9375. ck_krb4_list_creds(struct krb_op_data * op)
  9376. #else
  9377. ck_krb4_list_creds(op) struct krb_op_data * op;
  9378. #endif
  9379. {
  9380.     return(-1);
  9381. }
  9382. #else /* CK_KERBEROS */
  9383. int ck_krb4_initTGT(void * a, void *b)
  9384. {
  9385.     return(-1);
  9386. }
  9387. int ck_krb4_destroy(void *a)
  9388. {
  9389.     return(-1);
  9390. }
  9391. int ck_krb4_list_creds(void *a)
  9392. {
  9393.     return(-1);
  9394. }
  9395. #endif /* CK_KERBEROS */
  9396. #endif /* KRB4 */
  9397.  
  9398. /* The following functions are used to implement the Kermit Script Language */
  9399. /* functions                                                                */
  9400.  
  9401. struct tkt_list_item {
  9402.     char * name;
  9403.     struct tkt_list_item * next;
  9404. };
  9405.  
  9406. static struct tkt_list_item * k4_tkt_list = NULL;
  9407.  
  9408. int
  9409. #ifdef CK_ANSIC
  9410. ck_krb4_get_tkts(VOID)
  9411. #else
  9412. ck_krb4_get_tkts()
  9413. #endif
  9414. {
  9415. #ifdef KRB4
  9416.     char   *file=NULL;
  9417.     char    pname[ANAME_SZ];
  9418.     char    pinst[INST_SZ];
  9419.     char    prealm[REALM_SZ];
  9420.     char    buf1[20], buf2[20];
  9421.     int     k_errno;
  9422. #ifdef OS2
  9423.     LEASH_CREDENTIALS creds;
  9424. #else /* OS2 */
  9425.     CREDENTIALS creds;
  9426. #endif /* OS2 */
  9427.     int     tkt_count=0;
  9428.     struct  tkt_list_item ** list = &k4_tkt_list;
  9429.  
  9430.     while ( k4_tkt_list ) {
  9431.         struct tkt_list_item * next;
  9432.         next = k4_tkt_list->next;
  9433.         free(k4_tkt_list->name);
  9434.         free(k4_tkt_list);
  9435.         k4_tkt_list = next;
  9436.     }
  9437.  
  9438.     if ( !ck_krb4_is_installed() )
  9439.         return(-1);
  9440.  
  9441.     file = tkt_string();
  9442.  
  9443.     /*
  9444.      * Since krb_get_tf_realm will return a ticket_file error,
  9445.      * we will call tf_init and tf_close first to filter out
  9446.      * things like no ticket file.  Otherwise, the error that
  9447.      * the user would see would be
  9448.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9449.      * instead of
  9450.      * klist: No ticket file (tf_util)
  9451.      */
  9452.  
  9453.     /* Open ticket file */
  9454.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9455.         return(-1);
  9456.     }
  9457.  
  9458.     /* Close ticket file */
  9459.     (void) tf_close();
  9460.  
  9461.     /*
  9462.      * We must find the realm of the ticket file here before calling
  9463.      * tf_init because since the realm of the ticket file is not
  9464.      * really stored in the principal section of the file, the
  9465.      * routine we use must itself call tf_init and tf_close.
  9466.      */
  9467.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9468.         return(-1);
  9469.     }
  9470.  
  9471.     /* Open ticket file */
  9472.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9473.         return(-1);
  9474.     }
  9475.     /* Get principal name and instance */
  9476.     if ((k_errno = tf_get_pname(pname)) ||
  9477.          (k_errno = tf_get_pinst(pinst))) {
  9478.         return(-1);
  9479.     }
  9480.  
  9481.     /*
  9482.      * You may think that this is the obvious place to get the
  9483.      * realm of the ticket file, but it can't be done here as the
  9484.      * routine to do this must open the ticket file.  This is why
  9485.      * it was done before tf_init.
  9486.      */
  9487.  
  9488.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9489.         char tkt_buf[256];
  9490.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9491.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9492.                  (creds.realm[0] ? "@" : ""), creds.realm,
  9493.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9494.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  9495.         (*list)->name = strdup(tkt_buf);
  9496.         (*list)->next = NULL;
  9497.         list = &((*list)->next);
  9498.         tkt_count++;
  9499.     }
  9500.  
  9501.     tf_close();
  9502.     return(tkt_count);
  9503. #else /* KRB4 */
  9504.     return(0);
  9505. #endif /* KRB4 */
  9506. }
  9507.  
  9508. char *
  9509. #ifdef CK_ANSIC
  9510. ck_krb4_get_next_tkt(VOID)
  9511. #else
  9512. ck_krb4_get_next_tkt()
  9513. #endif
  9514. {
  9515. #ifdef KRB4
  9516.     static char * s=NULL;
  9517.     struct tkt_list_item * next=NULL;
  9518.  
  9519.     if ( s ) {
  9520.         free(s);
  9521.         s = NULL;
  9522.     }
  9523.  
  9524.     if ( k4_tkt_list == NULL )
  9525.         return(NULL);
  9526.  
  9527.     next = k4_tkt_list->next;
  9528.     s = k4_tkt_list->name;
  9529.     free(k4_tkt_list);
  9530.     k4_tkt_list = next;
  9531.     return(s);
  9532. #else /* KRB4 */
  9533.     return(NULL);
  9534. #endif /* KRB4 */
  9535. }
  9536.  
  9537. int
  9538. #ifdef CK_ANSIC
  9539. ck_krb4_tkt_isvalid(char * tktname)
  9540. #else
  9541. ck_krb4_tkt_isvalid(tktname) char * tktname;
  9542. #endif
  9543. {
  9544. #ifdef KRB4
  9545.     char   *file=NULL;
  9546.     char    pname[ANAME_SZ];
  9547.     char    pinst[INST_SZ];
  9548.     char    prealm[REALM_SZ];
  9549.     char    buf1[20], buf2[20];
  9550.     int     k_errno;
  9551.     time_t  issue_t, expire_t, now_t;
  9552. #ifdef OS2
  9553.     LEASH_CREDENTIALS creds;
  9554. #else /* OS2 */
  9555.     CREDENTIALS creds;
  9556. #endif /* OS2 */
  9557.  
  9558.     if ( !ck_krb4_is_installed() )
  9559.         return(-1);
  9560.  
  9561.     debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
  9562.     file = tkt_string();
  9563.  
  9564.     /*
  9565.      * Since krb_get_tf_realm will return a ticket_file error,
  9566.      * we will call tf_init and tf_close first to filter out
  9567.      * things like no ticket file.  Otherwise, the error that
  9568.      * the user would see would be
  9569.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9570.      * instead of
  9571.      * klist: No ticket file (tf_util)
  9572.      */
  9573.  
  9574.     /* Open ticket file */
  9575.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  9576.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9577.         return(-1);
  9578.     }
  9579.  
  9580.     /* Close ticket file */
  9581.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9582.     (void) tf_close();
  9583.  
  9584.     /*
  9585.      * We must find the realm of the ticket file here before calling
  9586.      * tf_init because since the realm of the ticket file is not
  9587.      * really stored in the principal section of the file, the
  9588.      * routine we use must itself call tf_init and tf_close.
  9589.      */
  9590.     debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
  9591.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9592.         return(-1);
  9593.     }
  9594.  
  9595.     /* Open ticket file */
  9596.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  9597.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9598.         return(-1);
  9599.     }
  9600.     /* Get principal name and instance */
  9601.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
  9602.     if ((k_errno = tf_get_pname(pname)) ||
  9603.          (k_errno = tf_get_pinst(pinst))) {
  9604.  
  9605.         /* Close ticket file */
  9606.         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9607.         (void) tf_close();
  9608.  
  9609.         return(-1);
  9610.     }
  9611.  
  9612.     /*
  9613.      * You may think that this is the obvious place to get the
  9614.      * realm of the ticket file, but it can't be done here as the
  9615.      * routine to do this must open the ticket file.  This is why
  9616.      * it was done before tf_init.
  9617.      */
  9618.  
  9619.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
  9620.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9621.         char tkt_buf[256];
  9622.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9623.                  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  9624.                  (creds.realm[0] ? "@" : ""), creds.realm,
  9625.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9626.         if ( !strcmp(tktname,tkt_buf) ) {
  9627.  
  9628.             /* we found the ticket we are looking for */
  9629.             issue_t = creds.issue_date;
  9630.             expire_t = creds.issue_date
  9631.                 + ((unsigned char) creds.lifetime) * 5 * 60;
  9632.             now_t = time(0);
  9633.  
  9634.             /* We add a 5 minutes fudge factor to compensate for potential */
  9635.             /* clock skew errors between the KDC and K95's host OS         */
  9636.  
  9637.             if ( now_t >= (issue_t-300) && now_t < expire_t) {
  9638. #ifdef OS2
  9639. #ifdef CHECKADDRS
  9640.                 if ( krb4_checkaddrs ) {
  9641.                     extern char myipaddr[20];       /* From ckcnet.c */
  9642.                     if ( !myipaddr[0] ) {
  9643.                         int i;
  9644.                         char buf[60];
  9645.                         for ( i=0;i<64;i++ ) {
  9646.                             if ( getlocalipaddrs(buf,60,i) < 0 )
  9647.                                 break;
  9648.  
  9649.                             if ( !strcmp(buf,creds.address) ) {
  9650.                                 /* Close ticket file */
  9651.                                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9652.                                 (void) tf_close();
  9653.                                 return(1); /* They're the same */
  9654.                             }
  9655.                         }
  9656.  
  9657.                         /* Close ticket file */
  9658.                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9659.                         (void) tf_close();
  9660.                         return(0);                  /* They're different */
  9661.                     } else if ( strcmp(myipaddr,creds.address) ) {
  9662.                         /* Close ticket file */
  9663.                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9664.                         (void) tf_close();
  9665.                         return(0);                  /* They're different */
  9666.                     }
  9667.                     else {
  9668.                         /* Close ticket file */
  9669.                         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9670.                         (void) tf_close();
  9671.                         return(1);                  /* They're the same */
  9672.                     }
  9673.                 } else {
  9674.                     /* Close ticket file */
  9675.                     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9676.                     (void) tf_close();
  9677.                     return(1);                  /* They're the same */
  9678.                 }
  9679. #else /* CHECKADDRS */
  9680.                 /* Close ticket file */
  9681.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9682.                 (void) tf_close();
  9683.                 return(1);      /* valid but no ip address check */
  9684. #endif /* CHECKADDRS */
  9685. #else /* OS2 */
  9686.                 /* Close ticket file */
  9687.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9688.                 (void) tf_close();
  9689.                 return(1);      /* Valid but no ip address check */
  9690. #endif /* OS2 */
  9691.             }
  9692.             else {
  9693.                 /* Close ticket file */
  9694.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9695.                 (void) tf_close();
  9696.                 return(0);      /* expired or otherwise invalid */
  9697.             }
  9698.         }
  9699.     }
  9700.     /* Close ticket file */
  9701.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  9702.     (void) tf_close();
  9703.     return(0);                  /* could not find the desired ticket */
  9704. #else /* KRB4 */
  9705.     return(-1);
  9706. #endif /* KRB4 */
  9707. }
  9708.  
  9709. int
  9710. #ifdef CK_ANSIC
  9711. ck_krb4_is_tgt_valid(VOID)
  9712. #else
  9713. ck_krb4_is_tgt_valid()
  9714. #endif
  9715. {
  9716. #ifdef KRB4
  9717.     char tgt[256];
  9718.     char * s;
  9719.     int rc = 0;
  9720.  
  9721.     s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
  9722.     ckmakmsg(tgt,sizeof(tgt),"krbtgt.",s,"@",s);
  9723.     rc = ck_krb4_tkt_isvalid(tgt);
  9724.     debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
  9725.     return(rc > 0);
  9726. #else /* KRB4 */
  9727.     return(0);
  9728. #endif /* KRB4 */
  9729. }
  9730.  
  9731. int
  9732. #ifdef CK_ANSIC
  9733. ck_krb4_tkt_time(char * tktname)
  9734. #else
  9735. ck_krb4_tkt_time(tktname) char * tktname;
  9736. #endif
  9737. {
  9738. #ifdef KRB4
  9739.     char   *file=NULL;
  9740.     char    pname[ANAME_SZ];
  9741.     char    pinst[INST_SZ];
  9742.     char    prealm[REALM_SZ];
  9743.     char    buf1[20], buf2[20];
  9744.     int     k_errno;
  9745. #ifdef OS2
  9746.     LEASH_CREDENTIALS creds;
  9747. #else /* OS2 */
  9748.     CREDENTIALS creds;
  9749. #endif /* OS2 */
  9750.  
  9751.     if ( !ck_krb4_is_installed() )
  9752.         return(-1);
  9753.  
  9754.     file = tkt_string();
  9755.  
  9756.     /*
  9757.      * Since krb_get_tf_realm will return a ticket_file error,
  9758.      * we will call tf_init and tf_close first to filter out
  9759.      * things like no ticket file.  Otherwise, the error that
  9760.      * the user would see would be
  9761.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  9762.      * instead of
  9763.      * klist: No ticket file (tf_util)
  9764.      */
  9765.  
  9766.     /* Open ticket file */
  9767.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9768.         return(-1);
  9769.     }
  9770.  
  9771.     /* Close ticket file */
  9772.     (void) tf_close();
  9773.  
  9774.     /*
  9775.      * We must find the realm of the ticket file here before calling
  9776.      * tf_init because since the realm of the ticket file is not
  9777.      * really stored in the principal section of the file, the
  9778.      * routine we use must itself call tf_init and tf_close.
  9779.      */
  9780.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  9781.         return(-1);
  9782.     }
  9783.  
  9784.     /* Open ticket file */
  9785.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  9786.         return(-1);
  9787.     }
  9788.     /* Get principal name and instance */
  9789.     if ((k_errno = tf_get_pname(pname)) ||
  9790.          (k_errno = tf_get_pinst(pinst))) {
  9791.         tf_close();
  9792.         return(-1);
  9793.     }
  9794.  
  9795.     /*
  9796.      * You may think that this is the obvious place to get the
  9797.      * realm of the ticket file, but it can't be done here as the
  9798.      * routine to do this must open the ticket file.  This is why
  9799.      * it was done before tf_init.
  9800.      */
  9801.  
  9802.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  9803.         char tkt_buf[256];
  9804.         ckmakxmsg(tkt_buf,sizeof(tkt_buf),
  9805.                  creds.service, (creds.instance[0] ? "." : ""),
  9806.                  creds.instance,
  9807.                  (creds.realm[0] ? "@" : ""), creds.realm,
  9808.                  NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  9809.         if ( !strcmp(tktname,tkt_buf) ) {
  9810.             /* we found the ticket we are looking for */
  9811.             int n = (creds.issue_date
  9812.                       + (((unsigned char) creds.lifetime) * 5 * 60))
  9813.                 - time(0);
  9814.             tf_close();
  9815.             return(n <= 0 ? 0 : n);
  9816.         }
  9817.     }
  9818.     tf_close();
  9819.     return(0);                  /* could not find the desired ticket */
  9820. #else /* KRB4 */
  9821.     return(-1);
  9822. #endif /* KRB4 */
  9823. }
  9824.  
  9825. char *
  9826. #ifdef CK_ANSIC
  9827. ck_krb4_getrealm(void)
  9828. #else
  9829. ck_krb4_getrealm()
  9830. #endif
  9831. {
  9832. #ifdef KRB4
  9833.     char   *file=NULL;
  9834.     int     k_errno;
  9835.     static char realm[256]="";
  9836.     realm[0]='\0';
  9837.  
  9838.     if ( !ck_krb4_is_installed() )
  9839.         return(realm);
  9840.  
  9841.     /* Try to get realm from ticket file */
  9842.     /* If failure get the local realm    */
  9843.  
  9844.     /*
  9845.     * Since krb_get_tf_realm will return a ticket_file error,
  9846.     * we will call tf_init and tf_close first to filter out
  9847.     * things like no ticket file.
  9848.     */
  9849.  
  9850.     /* Open ticket file */
  9851.     file = tkt_string();
  9852.     if (file == NULL || !file[0])
  9853.         return(realm);
  9854.  
  9855.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  9856.         /* Close ticket file */
  9857.         (void) tf_close();
  9858.  
  9859.         k_errno = krb_get_tf_realm(file, realm);
  9860.     }
  9861.     if (k_errno != KSUCCESS) {
  9862.         k_errno = krb_get_lrealm(realm, 1);
  9863.     }
  9864.     return(realm);
  9865. #else /* KRB4 */
  9866.     return("");
  9867. #endif /* KRB4 */
  9868. }
  9869.  
  9870. char *
  9871. #ifdef CK_ANSIC
  9872. ck_krb4_getprincipal(void)
  9873. #else
  9874. ck_krb4_getprincipal()
  9875. #endif
  9876. {
  9877. #ifdef KRB4
  9878.     char   *file=NULL;
  9879.     int     k_errno;
  9880.     static char principal[256]="";
  9881.     char        instance[256]="";
  9882.     char        realm[256]="";
  9883.     principal[0]='\0';
  9884.  
  9885.     if ( !ck_krb4_is_installed() )
  9886.         return(principal);
  9887.  
  9888.     /* Try to get realm from ticket file */
  9889.     /* If failure get the local realm    */
  9890.  
  9891.     /*
  9892.     * Since krb_get_tf_realm will return a ticket_file error,
  9893.     * we will call tf_init and tf_close first to filter out
  9894.     * things like no ticket file.
  9895.     */
  9896.  
  9897.     /* Open ticket file */
  9898.     file = tkt_string();
  9899.     if (file == NULL || !file[0])
  9900.         return(principal);
  9901.  
  9902.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  9903.         /* Close ticket file */
  9904.         (void) tf_close();
  9905.  
  9906.         k_errno = krb_get_tf_fullname(file, principal, instance, realm);
  9907.     }
  9908.     return(principal);
  9909. #else /* KRB4 */
  9910.     return("");
  9911. #endif /* KRB4 */
  9912. }
  9913.  
  9914. static struct tkt_list_item * k5_tkt_list = NULL;
  9915.  
  9916. int
  9917. #ifdef CK_ANSIC
  9918. ck_krb5_get_tkts(char * cc_name)
  9919. #else
  9920. ck_krb5_get_tkts(cc_name) char * cc_name;
  9921. #endif
  9922. {
  9923. #ifdef KRB5
  9924. #ifndef HEIMDAL
  9925.     krb5_context kcontext;
  9926.     krb5_error_code retval;
  9927.     krb5_ccache cache = NULL;
  9928.     krb5_cc_cursor cur;
  9929.     krb5_creds creds;
  9930.     krb5_principal princ=NULL;
  9931.     krb5_flags flags=0;
  9932.     krb5_error_code code=0;
  9933.     int exit_status = 0;
  9934.  
  9935.     int     tkt_count=0;
  9936.     struct  tkt_list_item ** list = &k5_tkt_list;
  9937.  
  9938.     while ( k5_tkt_list ) {
  9939.         struct tkt_list_item * next;
  9940.         next = k5_tkt_list->next;
  9941.         free(k5_tkt_list->name);
  9942.         free(k5_tkt_list);
  9943.         k5_tkt_list = next;
  9944.     }
  9945.  
  9946.     if ( !ck_krb5_is_installed() )
  9947.         return(-1);
  9948.  
  9949.     retval = krb5_init_context(&kcontext);
  9950.     if (retval) {
  9951.         debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
  9952.         return(-1);
  9953.     }
  9954.  
  9955.     code = k5_get_ccache(kcontext,&cache,cc_name);
  9956.     if (code != 0) {
  9957.         debug(F111,"ck_krb5_get_tkts while getting ccache",
  9958.                error_message(code),code);
  9959.         tkt_count = -1;
  9960.         goto exit_k5_get_tkt;
  9961.     }
  9962.  
  9963.     flags = 0;                          /* turns off OPENCLOSE mode */
  9964.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  9965.         if (code == ENOENT) {
  9966.             debug(F111,"ck_krb5_get_tkts (ticket cache)",
  9967.                    krb5_cc_get_name(kcontext, cache),code);
  9968.         } else {
  9969.             debug(F111,
  9970.                  "ck_krb5_get_tkts while setting cache flags (ticket cache)",
  9971.                   krb5_cc_get_name(kcontext, cache),code);
  9972.         }
  9973.         tkt_count = -1;
  9974.         goto exit_k5_get_tkt;
  9975.     }
  9976.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  9977.         debug(F101,"ck_krb5_get_tkts while retrieving principal name",
  9978.                "",code);
  9979.         tkt_count = -1;
  9980.         goto exit_k5_get_tkt;
  9981.     }
  9982.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  9983.         debug(F101,"ck_krb5_get_tkts while unparsing principal name",
  9984.                "",code);
  9985.         tkt_count = -1;
  9986.         goto exit_k5_get_tkt;
  9987.     }
  9988.  
  9989.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  9990.         debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
  9991.                "",code);
  9992.         tkt_count = -1;
  9993.         goto exit_k5_get_tkt;
  9994.     }
  9995.  
  9996.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  9997.         char *sname=NULL;
  9998.  
  9999.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10000.         if (retval) {
  10001.             debug(F101,
  10002.                   "ck_krb5_get_tkts while unparsing server name","",retval);
  10003.             tkt_count = -1;
  10004.             goto exit_k5_get_tkt;
  10005.         }
  10006.  
  10007.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  10008.         (*list)->name = sname;
  10009.         (*list)->next = NULL;
  10010.         list = &((*list)->next);
  10011.  
  10012.         krb5_free_cred_contents(kcontext, &creds);
  10013.         tkt_count++;
  10014.     }
  10015.  
  10016.     if (code == KRB5_CC_END) {
  10017.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10018.             debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
  10019.                    "",code);
  10020.             tkt_count = -1;
  10021.             goto exit_k5_get_tkt;
  10022.         }
  10023.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10024.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10025.             debug(F101,"ck_krb5_get_tkts while closing ccache",
  10026.                    "",code);
  10027.             tkt_count = -1;
  10028.             goto exit_k5_get_tkt;
  10029.         }
  10030.     } else {
  10031.         debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
  10032.         tkt_count = -1;
  10033.         goto exit_k5_get_tkt;
  10034.     }
  10035.  
  10036.   exit_k5_get_tkt:
  10037.     krb5_free_principal(kcontext,princ);
  10038.     krb5_free_unparsed_name(kcontext,defname);
  10039.     krb5_cc_close(kcontext,cache);
  10040.     krb5_free_context(kcontext);
  10041.     return(tkt_count);
  10042. #else /* HEIMDAL */
  10043.     return(-1);
  10044. #endif /* HEIMDAL */
  10045. #else /* KRB5 */
  10046.     return(0);
  10047. #endif /* KRB5 */
  10048. }
  10049.  
  10050. char *
  10051. #ifdef CK_ANSIC
  10052. ck_krb5_get_next_tkt(VOID)
  10053. #else
  10054. ck_krb5_get_next_tkt()
  10055. #endif
  10056. {
  10057. #ifdef KRB5
  10058. #ifndef HEIMDAL
  10059.     static char * s=NULL;
  10060.     struct tkt_list_item * next=NULL;
  10061.  
  10062.     if ( s ) {
  10063.         free(s);
  10064.         s = NULL;
  10065.     }
  10066.  
  10067.     if ( k5_tkt_list == NULL )
  10068.         return(NULL);
  10069.  
  10070.     next = k5_tkt_list->next;
  10071.     s = k5_tkt_list->name;
  10072.     free(k5_tkt_list);
  10073.     k5_tkt_list = next;
  10074.     return(s);
  10075. #else /* HEIMDAL */
  10076.     return("Not implemented");
  10077. #endif /* HEIMDAL */
  10078. #else /* KRB5 */
  10079.     return(NULL);
  10080. #endif /* KRB5 */
  10081. }
  10082.  
  10083. char *
  10084. #ifdef CK_ANSIC
  10085. ck_krb5_tkt_flags(char * cc_name, char * tktname)
  10086. #else
  10087. ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
  10088. #endif
  10089. {
  10090. #ifdef KRB5
  10091. #ifndef HEIMDAL
  10092.     krb5_context kcontext;
  10093.     krb5_error_code retval;
  10094.     krb5_ccache cache = NULL;
  10095.     krb5_cc_cursor cur;
  10096.     krb5_creds creds;
  10097.     krb5_principal princ=NULL;
  10098.     krb5_flags flags=0;
  10099.     krb5_error_code code=0;
  10100.     char * flag_str = "";
  10101.  
  10102.     if ( !ck_krb5_is_installed() )
  10103.         return("");
  10104.  
  10105.     retval = krb5_init_context(&kcontext);
  10106.     if (retval) {
  10107.         debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
  10108.         return("");
  10109.     }
  10110.  
  10111.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10112.     if (code != 0) {
  10113.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  10114.                error_message(code),code);
  10115.         goto exit_k5_get_tkt;
  10116.     }
  10117.  
  10118.     flags = 0;                          /* turns off OPENCLOSE mode */
  10119.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10120.         if (code == ENOENT) {
  10121.             debug(F111,"ck_krb5_tkt_flags (ticket cache)",
  10122.                    krb5_cc_get_name(kcontext, cache),code);
  10123.         } else {
  10124.             debug(F111,
  10125.                  "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
  10126.                   krb5_cc_get_name(kcontext, cache),code);
  10127.         }
  10128.         retval = -1;
  10129.         goto exit_k5_get_tkt;
  10130.     }
  10131.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10132.         debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
  10133.                "",code);
  10134.         retval = -1;
  10135.         goto exit_k5_get_tkt;
  10136.     }
  10137.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10138.         debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
  10139.                "",code);
  10140.         retval = -1;
  10141.         goto exit_k5_get_tkt;
  10142.     }
  10143.  
  10144.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10145.         debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
  10146.                "",code);
  10147.         retval = -1;
  10148.         goto exit_k5_get_tkt;
  10149.     }
  10150.  
  10151.     if ((code = krb5_timeofday(kcontext, &now))) {
  10152.         if (!status_only)
  10153.             debug(F101,"ck_krb5_tkt_flags while getting time of day.",
  10154.                    "",code);
  10155.         retval = -1;
  10156.         goto exit_k5_get_tkt;
  10157.     }
  10158.  
  10159.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10160.         char *sname=NULL;
  10161.  
  10162.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10163.         if (retval) {
  10164.             debug(F101,
  10165.                   "ck_krb5_tkt_flags while unparsing server name","",retval);
  10166.             retval = -1;
  10167.             krb5_free_cred_contents(kcontext, &creds);
  10168.             goto exit_k5_get_tkt;
  10169.         }
  10170.  
  10171.         if ( !strcmp(sname,tktname) ) {
  10172.             /* we found the ticket we are looking for */
  10173.  
  10174.             flag_str = flags_string(&creds);
  10175.  
  10176.             krb5_free_cred_contents(kcontext, &creds);
  10177.             code = KRB5_CC_END;
  10178.             break;
  10179.         }
  10180.         krb5_free_cred_contents(kcontext, &creds);
  10181.     }
  10182.  
  10183.     if (code == KRB5_CC_END) {
  10184.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10185.             debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
  10186.                    "",code);
  10187.             goto exit_k5_get_tkt;
  10188.         }
  10189.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10190.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10191.             debug(F101,"ck_krb5_tkt_flags while closing ccache",
  10192.                    "",code);
  10193.             goto exit_k5_get_tkt;
  10194.         }
  10195.     } else {
  10196.         debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
  10197.         goto exit_k5_get_tkt;
  10198.     }
  10199.  
  10200.   exit_k5_get_tkt:
  10201.     krb5_free_principal(kcontext,princ);
  10202.     krb5_free_unparsed_name(kcontext,defname);
  10203.     krb5_cc_close(kcontext,cache);
  10204.     krb5_free_context(kcontext);
  10205.     return(flag_str);
  10206. #else /* HEIMDAL */
  10207.     return("Not implemented");
  10208. #endif /* HEIMDAL */
  10209. #else /* KRB5 */
  10210.     return("");
  10211. #endif /* KRB5 */
  10212. }
  10213.  
  10214.  
  10215. int
  10216. #ifdef CK_ANSIC
  10217. ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
  10218. #else
  10219. ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
  10220. #endif
  10221. {
  10222. #ifdef KRB5
  10223. #ifndef HEIMDAL
  10224.     krb5_context kcontext=NULL;
  10225.     krb5_error_code retval;
  10226.     krb5_ccache cache = NULL;
  10227.     krb5_cc_cursor cur;
  10228.     krb5_creds creds;
  10229.     krb5_principal princ=NULL;
  10230.     krb5_flags flags=0;
  10231.     krb5_error_code code=0;
  10232. #ifdef CHECKADDRS
  10233.     krb5_address **     myAddrs=NULL;
  10234.     krb5_address **     p=NULL;
  10235.     BOOL                Addrfound = FALSE;
  10236. #endif /*CHECKADDRS*/
  10237.  
  10238.     if ( !ck_krb5_is_installed() )
  10239.         return(-1);
  10240.  
  10241.     retval = krb5_init_context(&kcontext);
  10242.     if (retval) {
  10243.         debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
  10244.         return(-1);
  10245.     }
  10246.  
  10247.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10248.     if (code != 0) {
  10249.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  10250.                error_message(code),code);
  10251.         goto exit_k5_get_tkt;
  10252.     }
  10253.  
  10254.     flags = 0;                          /* turns off OPENCLOSE mode */
  10255.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10256.         if (code == ENOENT) {
  10257.             debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
  10258.                    krb5_cc_get_name(kcontext, cache),code);
  10259.         } else {
  10260.             debug(F111,
  10261.                 "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
  10262.                   krb5_cc_get_name(kcontext, cache),code);
  10263.         }
  10264.         retval = -1;
  10265.         goto exit_k5_get_tkt;
  10266.     }
  10267.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10268.         debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
  10269.                "",code);
  10270.         retval = -1;
  10271.         goto exit_k5_get_tkt;
  10272.     }
  10273.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10274.         debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
  10275.                "",code);
  10276.         retval = -1;
  10277.         goto exit_k5_get_tkt;
  10278.     }
  10279.  
  10280.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10281.         debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
  10282.                "",code);
  10283.         retval = -1;
  10284.         goto exit_k5_get_tkt;
  10285.     }
  10286.  
  10287.     if ((code = krb5_timeofday(kcontext, &now))) {
  10288.         if (!status_only)
  10289.             debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
  10290.                    "",code);
  10291.         retval = -1;
  10292.         goto exit_k5_get_tkt;
  10293.     }
  10294.  
  10295.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10296.         char *sname=NULL;
  10297.  
  10298.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10299.         if (retval) {
  10300.             debug(F101,
  10301.                   "ck_krb5_tkt_isvalid while unparsing server name","",retval);
  10302.             retval = -1;
  10303.             krb5_free_cred_contents(kcontext, &creds);
  10304.             goto exit_k5_get_tkt;
  10305.         }
  10306.  
  10307.         if ( !strcmp(sname,tktname) ) {
  10308.             /* we found the ticket we are looking for */
  10309.  
  10310.             /* We add a 5 minutes fudge factor to compensate for potential */
  10311.             /* clock skew errors between the KDC and K95's host OS         */
  10312.  
  10313.             retval = ((creds.times.starttime > 0) &&
  10314.                        now >= (creds.times.starttime - 300) &&
  10315.                        now < (creds.times.endtime + 300) &&
  10316.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  10317.  
  10318. #ifdef CHECKADDRS
  10319.             if ( retval && krb5_checkaddrs &&
  10320.                                  creds.addresses && creds.addresses[0] ) {
  10321.                 /* if we think it is valid, then lets check the IP Addresses */
  10322.                 /* to make sure it is valid for our current connection.      */
  10323.                 /* Also make sure it's for the correct IP address */
  10324.                 retval = krb5_os_localaddr(kcontext, &myAddrs);
  10325.                 if (retval) {
  10326.                     com_err(NULL, retval, "retrieving my IP address");
  10327.                     krb5_free_cred_contents(kcontext, &creds);
  10328.                     code = KRB5_CC_END;
  10329.                     retval = -1;
  10330.                     break;
  10331.                 }
  10332.  
  10333.              /* See if any of our addresses match any in cached credentials */
  10334.  
  10335.                 for (Addrfound=FALSE, p=myAddrs;
  10336.                      (Addrfound==FALSE) && (*p);
  10337.                      p++
  10338.                      ) {
  10339.                     if (krb5_address_search(kcontext, *p, creds.addresses)) {
  10340.                         Addrfound = TRUE;
  10341.                     }
  10342.                 }
  10343.                 krb5_free_addresses(k5_context, myAddrs);
  10344.  
  10345.                 if (Addrfound) {
  10346.                     krb5_free_cred_contents(kcontext, &creds);
  10347.                     code = KRB5_CC_END;
  10348.                     retval = 1;
  10349.                     break;
  10350.                 } else {
  10351.                     krb5_free_cred_contents(kcontext, &creds);
  10352.                     code = KRB5_CC_END;
  10353.                     retval = 0;
  10354.                     break;
  10355.                 }
  10356.             }
  10357. #endif /* CHECKADDRS */
  10358.  
  10359.             krb5_free_cred_contents(kcontext, &creds);
  10360.             code = KRB5_CC_END;
  10361.             break;
  10362.         }
  10363.         krb5_free_cred_contents(kcontext, &creds);
  10364.     }
  10365.  
  10366.     if (code == KRB5_CC_END) {
  10367.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10368.             debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
  10369.                    "",code);
  10370.             retval = -1;
  10371.             goto exit_k5_get_tkt;
  10372.         }
  10373.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10374.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10375.             debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
  10376.                    "",code);
  10377.             retval = -1;
  10378.             goto exit_k5_get_tkt;
  10379.         }
  10380.     } else {
  10381.         debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
  10382.         retval = -1;
  10383.         goto exit_k5_get_tkt;
  10384.     }
  10385.  
  10386.   exit_k5_get_tkt:
  10387.     krb5_free_principal(kcontext,princ);
  10388.     krb5_free_unparsed_name(kcontext,defname);
  10389.     krb5_cc_close(kcontext,cache);
  10390.     krb5_free_context(kcontext);
  10391.     return(retval);
  10392. #else /* HEIMDAL */
  10393.     return(-1);
  10394. #endif /* HEIMDAL */
  10395. #else /* KRB5 */
  10396.     return(-1);
  10397. #endif /* KRB5 */
  10398. }
  10399.  
  10400. int
  10401. #ifdef CK_ANSIC
  10402. ck_krb5_is_tgt_valid(VOID)
  10403. #else
  10404. ck_krb5_is_tgt_valid()
  10405. #endif
  10406. {
  10407. #ifdef KRB5
  10408. #ifndef HEIMDAL
  10409.     char tgt[256];
  10410.     char * s;
  10411.     int rc = 0;
  10412.  
  10413.     s = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  10414.     ckmakmsg(tgt,sizeof(tgt),"krbtgt/",s,"@",s);
  10415.     rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
  10416.     debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
  10417.     return(rc>0);
  10418. #else /* HEIMDAL */
  10419.     return(-1);
  10420. #endif /* HEIMDAL */
  10421. #else /* KRB5 */
  10422.     return(0);
  10423. #endif /* KRB5 */
  10424. }
  10425.  
  10426. int
  10427. #ifdef CK_ANSIC
  10428. ck_krb5_tkt_time(char * cc_name, char * tktname)
  10429. #else
  10430. ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
  10431. #endif
  10432. {
  10433. #ifdef KRB5
  10434. #ifndef HEIMDAL
  10435.     krb5_context kcontext;
  10436.     krb5_error_code retval;
  10437.     krb5_ccache cache = NULL;
  10438.     krb5_cc_cursor cur;
  10439.     krb5_creds creds;
  10440.     krb5_principal princ=NULL;
  10441.     krb5_flags flags=0;
  10442.     krb5_error_code code=0;
  10443.  
  10444.     if ( !ck_krb5_is_installed() )
  10445.         return(-1);
  10446.  
  10447.     retval = krb5_init_context(&kcontext);
  10448.     if (retval) {
  10449.         debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
  10450.         return(-1);
  10451.     }
  10452.  
  10453.     code = k5_get_ccache(kcontext,&cache,cc_name);
  10454.     if (code != 0) {
  10455.         debug(F111,"ck_krb5_tkt_time while getting ccache",
  10456.                error_message(code),code);
  10457.         retval = -1;
  10458.         goto exit_k5_get_tkt;
  10459.     }
  10460.  
  10461.     flags = 0;                          /* turns off OPENCLOSE mode */
  10462.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10463.         if (code == ENOENT) {
  10464.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  10465.                    krb5_cc_get_name(kcontext, cache),code);
  10466.         } else {
  10467.             debug(F111,
  10468.                  "ck_krb5_list_creds while setting cache flags (ticket cache)",
  10469.                   krb5_cc_get_name(kcontext, cache),code);
  10470.         }
  10471.         retval = -1;
  10472.         goto exit_k5_get_tkt;
  10473.     }
  10474.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  10475.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  10476.                "",code);
  10477.         retval = -1;
  10478.         goto exit_k5_get_tkt;
  10479.     }
  10480.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  10481.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  10482.                "",code);
  10483.         retval = -1;
  10484.         goto exit_k5_get_tkt;
  10485.     }
  10486.  
  10487.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  10488.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  10489.                "",code);
  10490.         retval = -1;
  10491.         goto exit_k5_get_tkt;
  10492.     }
  10493.  
  10494.     if ((code = krb5_timeofday(kcontext, &now))) {
  10495.         if (!status_only)
  10496.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  10497.                    "",code);
  10498.         krb5_free_context(kcontext);
  10499.         return(-1);
  10500.     }
  10501.  
  10502.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  10503.         char *sname=NULL;
  10504.  
  10505.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  10506.         if (retval) {
  10507.             debug(F101,
  10508.                   "ck_krb5_list_creds while unparsing server name","",retval);
  10509.             retval = -1;
  10510.             krb5_free_cred_contents(kcontext, &creds);
  10511.             goto exit_k5_get_tkt;
  10512.         }
  10513.  
  10514.         if ( !strcmp(sname,tktname) ) {
  10515.             /* we found the ticket we are looking for */
  10516.             int valid = (creds.times.starttime &&
  10517.                        now > creds.times.starttime &&
  10518.                        now < creds.times.endtime &&
  10519.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  10520.             if ( valid ) {
  10521.                 retval = creds.times.endtime - now;
  10522.             }
  10523.             else
  10524.                 retval = 0;
  10525.             krb5_free_cred_contents(kcontext, &creds);
  10526.             code = KRB5_CC_END;
  10527.             break;
  10528.         }
  10529.         krb5_free_cred_contents(kcontext, &creds);
  10530.     }
  10531.  
  10532.     if (code == KRB5_CC_END) {
  10533.         if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  10534.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  10535.                    "",code);
  10536.             retval = -1;
  10537.             goto exit_k5_get_tkt;
  10538.         }
  10539.         flags = KRB5_TC_OPENCLOSE;      /* turns on OPENCLOSE mode */
  10540.         if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  10541.             debug(F101,"ck_krb5_list_creds while closing ccache",
  10542.                    "",code);
  10543.             retval = -1;
  10544.             goto exit_k5_get_tkt;
  10545.         }
  10546.     } else {
  10547.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  10548.         retval = -1;
  10549.         goto exit_k5_get_tkt;
  10550.     }
  10551.  
  10552.   exit_k5_get_tkt:
  10553.     krb5_free_principal(kcontext,princ);
  10554.     krb5_free_unparsed_name(kcontext,defname);
  10555.     krb5_cc_close(kcontext,cache);
  10556.     krb5_free_context(kcontext);
  10557.     return(retval);
  10558. #else /* HEIMDAL */
  10559.     return(-1);
  10560. #endif /* HEIMDAL */
  10561. #else /* KRB5 */
  10562.     return(-1);
  10563. #endif /* KRB5 */
  10564. }
  10565.  
  10566. char *
  10567. #ifdef CK_ANSIC
  10568. ck_krb5_get_cc_name(void)
  10569. #else
  10570. ck_krb5_get_cc_name()
  10571. #endif
  10572. {
  10573. #ifdef KRB5
  10574. #ifndef HEIMDAL
  10575.     static char cc_name[CKMAXPATH+1]="";
  10576.     krb5_context kcontext = NULL;
  10577.     krb5_ccache ccache = NULL;
  10578.     krb5_error_code code;
  10579.     char * p=NULL;
  10580.  
  10581.     cc_name[0] = '\0';
  10582.  
  10583.     if ( !ck_krb5_is_installed() )
  10584.         return(cc_name);
  10585.  
  10586.     p = getenv("KRB5CCNAME");
  10587.     if ( !p ) {
  10588.         code = krb5_init_context(&kcontext);
  10589.         if (code) {
  10590.             com_err("ck_krb5_get_cc_name",code,"while init_context");
  10591.             return(cc_name);
  10592.         }
  10593.         if ((code = krb5_cc_default(kcontext, &ccache))) {
  10594.             com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
  10595.             goto exit_k5_get_cc;
  10596.         }
  10597.  
  10598.         ckmakmsg(cc_name,sizeof(cc_name),krb5_cc_get_type(kcontext,ccache),":",
  10599.                  krb5_cc_get_name(kcontext,ccache),NULL);
  10600.     } else {
  10601.         ckstrncpy(cc_name,p,CKMAXPATH);
  10602.     }
  10603.  
  10604.     if ( !strncmp("FILE:",cc_name,5) ) {
  10605.         for ( p=cc_name; *p ; p++ )
  10606.             if ( *p == '\\' ) *p = '/';
  10607.     }
  10608.  
  10609.   exit_k5_get_cc:
  10610.     if ( ccache )
  10611.         krb5_cc_close(kcontext,ccache);
  10612.     if ( kcontext )
  10613.         krb5_free_context(kcontext);
  10614.     return(cc_name);
  10615. #else /* HEIMDAL */
  10616.     return("Not implemented");
  10617. #endif /* HEIMDAL */
  10618. #else /* KRB5 */
  10619.     return("");
  10620. #endif /* KRB5 */
  10621. }
  10622.  
  10623. char *
  10624. #ifdef CK_ANSIC
  10625. ck_krb5_getrealm(char * cc_name)
  10626. #else
  10627. ck_krb5_getrealm(cc_name) char * cc_name;
  10628. #endif
  10629. {
  10630. #ifdef KRB5
  10631. #ifndef HEIMDAL
  10632.     static char realm[256]="";
  10633.     krb5_context kcontext;
  10634.     krb5_ccache ccache = NULL;
  10635.     krb5_error_code code;
  10636.     krb5_principal me;
  10637.  
  10638.     realm[0] = '\0';
  10639.  
  10640.     if ( !ck_krb5_is_installed() )
  10641.         return(realm);
  10642.  
  10643.     code = krb5_init_context(&kcontext);
  10644.     if (code) {
  10645.         return(realm);
  10646.     }
  10647.  
  10648.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  10649.     if (code != 0) {
  10650.         goto exit_k5_getrealm;
  10651.     }
  10652.  
  10653.     if ((code = krb5_parse_name(kcontext, "foo", &me))) {
  10654.         goto exit_k5_getrealm;
  10655.     }
  10656.     if ( krb5_princ_realm(kcontext, me)->length < sizeof(realm) ) {
  10657.         memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  10658.                 krb5_princ_realm(kcontext, me)->length);        /* safe */
  10659.        realm[krb5_princ_realm(kcontext, me)->length]='\0';
  10660.     }
  10661.   exit_k5_getrealm:
  10662.     if ( ccache )
  10663.         krb5_cc_close(kcontext,ccache);
  10664.     if (kcontext)
  10665.         krb5_free_context(kcontext);
  10666.     return(realm);
  10667. #else /* HEIMDAL */
  10668.     return("Not implemented");
  10669. #endif /* HEIMDAL */
  10670. #else /* KRB5 */
  10671.     return("");
  10672. #endif /* KRB5 */
  10673. }
  10674.  
  10675. char *
  10676. #ifdef CK_ANSIC
  10677. ck_krb5_getprincipal(char * cc_name)
  10678. #else
  10679. ck_krb5_getprincipal(cc_name) char * cc_name;
  10680. #endif
  10681. {
  10682. #ifdef KRB5
  10683. #ifndef HEIMDAL
  10684.     static char principal[UIDBUFLEN+1]="";
  10685.     krb5_context kcontext;
  10686.     krb5_ccache ccache = NULL;
  10687.     krb5_error_code code;
  10688.     krb5_principal me;
  10689.     char * p=NULL;
  10690.     int i;
  10691.  
  10692.     principal[0] = '\0';
  10693.  
  10694.     if ( !ck_krb5_is_installed() )
  10695.         return(principal);
  10696.  
  10697.     code = krb5_init_context(&kcontext);
  10698.     if (code) {
  10699.         return(principal);
  10700.     }
  10701.  
  10702.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  10703.     if (code != 0) {
  10704.         goto exit_k5_getprincipal;
  10705.     }
  10706.  
  10707.     if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
  10708.         goto exit_k5_getprincipal;
  10709.     }
  10710.  
  10711.     if ((code = krb5_unparse_name (kcontext, me, &p))) {
  10712.         krb5_free_principal(kcontext,me);
  10713.         goto exit_k5_getprincipal;
  10714.     }
  10715.  
  10716.     ckstrncpy(principal,p,UIDBUFLEN);
  10717.     i = ckindex("@",principal,0,0,0);
  10718.     if (i)
  10719.       principal[i-1] = '\0';
  10720.  
  10721.     krb5_free_unparsed_name(kcontext,p);
  10722.  
  10723.   exit_k5_getprincipal:
  10724.     if ( ccache )
  10725.         krb5_cc_close(kcontext,ccache);
  10726.     if (kcontext)
  10727.         krb5_free_context(kcontext);
  10728.     return(principal);
  10729. #else /* HEIMDAL */
  10730.     return("Not implemented");
  10731. #endif /* HEIMDAL */
  10732. #else /* KRB5 */
  10733.     return("");
  10734. #endif /* KRB5 */
  10735. }
  10736.  
  10737. #ifndef CRYPT_DLL
  10738. int
  10739. ck_get_crypt_table(struct keytab ** pTable, int * pN)
  10740. {
  10741. #ifdef CK_ENCRYPTION
  10742.     return(get_crypt_table(pTable, pN));
  10743. #else /* ENCRYPTION */
  10744.     int i=0;
  10745. #ifndef OS2
  10746.     char * tmpstring = NULL;
  10747. #endif /* OS2 */
  10748.  
  10749.     if ( *pTable )
  10750.     {
  10751.         for ( i=0 ; i < *pN ; i++ )
  10752.             free( (*pTable)[i].kwd ) ;
  10753.         free ( *pTable )  ;
  10754.     }
  10755.     *pTable = NULL;
  10756.     *pN = 0;
  10757.  
  10758.     *pTable = malloc( sizeof(struct keytab) * 2 ) ;
  10759.     if ( !(*pTable) )
  10760.         return(0);
  10761.  
  10762. #ifdef OS2
  10763.     (*pTable)[0].kwd =strdup("automatic");
  10764. #else /* OS2 */
  10765.     makestr(&tmpstring,"automatic");
  10766.     (*pTable)[0].kwd = tmpstring;
  10767.     tmpstring = NULL;
  10768. #endif /* OS2 */
  10769.     (*pTable)[0].kwval = ENCTYPE_ANY;
  10770.     (*pTable)[0].flgs = 0;
  10771. #ifdef OS2
  10772.     (*pTable)[1].kwd =strdup("none");
  10773. #else /* OS2 */
  10774.     makestr(&tmpstring,"none");
  10775.     (*pTable)[1].kwd = tmpstring;
  10776.     tmpstring = NULL;
  10777. #endif /* OS2 */
  10778.     (*pTable)[1].kwval = 999;
  10779.     (*pTable)[1].flgs = 0;
  10780.     (*pN) = 2;
  10781.  
  10782.     return(2);
  10783. #endif /* ENCRYPTION */
  10784. }
  10785.  
  10786. VOID
  10787. ck_encrypt_send_support()
  10788. {
  10789. #ifdef CK_ENCRYPTION
  10790.     encrypt_send_support();
  10791. #endif /* ENCRYPTION */
  10792. }
  10793. #endif /* CRYPT_DLL */
  10794.  
  10795. /*
  10796.  *
  10797.  * Kstream
  10798.  *
  10799.  * Emulates the kstream package in Kerberos 4
  10800.  *
  10801.  */
  10802.  
  10803. int
  10804. kstream_destroy()
  10805. {
  10806.     if (g_kstream != NULL) {
  10807.         auth_destroy();                       /* Destroy authorizing */
  10808.         free(g_kstream);
  10809.         g_kstream=NULL;
  10810.     }
  10811.     return 0;
  10812. }
  10813.  
  10814. VOID
  10815. #ifdef CK_ANSIC
  10816. kstream_set_buffer_mode(int mode)
  10817. #else
  10818. kstream_set_buffer_mode(mode) int mode;
  10819. #endif
  10820. {
  10821. }
  10822.  
  10823.  
  10824. int
  10825. #ifdef CK_ANSIC
  10826. kstream_create_from_fd(int fd,
  10827.                        kstream_ptr data)
  10828. #else
  10829. kstream_create_from_fd(fd,data)
  10830.     int fd; kstream_ptr data;
  10831. #endif
  10832. {
  10833.     int n;
  10834.  
  10835.     g_kstream = malloc(sizeof(struct kstream_int));
  10836.     if (g_kstream == NULL)
  10837.         return 0;
  10838.  
  10839.     g_kstream->fd = fd;
  10840.  
  10841.     n = auth_init(g_kstream);                   /* Initialize authorizing */
  10842.     if (n) {
  10843.         free(g_kstream);
  10844.         g_kstream = NULL;
  10845.         return 0;
  10846.     }
  10847.  
  10848.     g_kstream->encrypt = NULL;
  10849.     g_kstream->decrypt = NULL;
  10850.     g_kstream->encrypt_type = ENCTYPE_ANY;
  10851.     g_kstream->decrypt_type = ENCTYPE_ANY;
  10852.     return 1;
  10853. }
  10854.  
  10855. #ifdef CK_KERBEROS
  10856. #ifdef RLOGCODE
  10857. #ifdef MIT_CURRENT
  10858. static int do_lencheck, do_inband;
  10859.  
  10860. void rcmd_stream_init_krb5(in_keyblock, encrypt_flag, lencheck, am_client)
  10861.      krb5_keyblock *in_keyblock;
  10862.      int encrypt_flag;
  10863.      int lencheck;
  10864.      int am_client;
  10865. {
  10866.     krb5_error_code status;
  10867.     size_t blocksize;
  10868.     krb5_boolean similar;
  10869.  
  10870.     if (!encrypt_flag)
  10871.         return;
  10872.  
  10873.     desinbuf.data = des_inbuf;
  10874.     desoutbuf.data = des_outpkt+4;      /* Set up des buffers */
  10875.     k5_session_key = in_keyblock;
  10876.  
  10877.     do_lencheck = lencheck;
  10878.  
  10879.     if (status = krb5_c_enctype_compare(k5_context, ENCTYPE_DES_CBC_CRC,
  10880.                                         k5_session_key->enctype,
  10881.                                         &similar)) {
  10882.         /* XXX what do I do? */
  10883.         return;
  10884.     }
  10885.  
  10886.     if (similar) {
  10887.         encivec_i.length = encivec_o.length = 0;
  10888.         return;
  10889.     }
  10890.  
  10891.     if (status = krb5_c_block_size(k5_context, k5_session_key->enctype,
  10892.                                    &blocksize)) {
  10893.         /* XXX what do I do? */
  10894.         return;
  10895.     }
  10896.  
  10897.     encivec_i.length = encivec_o.length = blocksize;
  10898.  
  10899.     if ((encivec_i.data = malloc(encivec_i.length * 2)) == NULL) {
  10900.         /* XXX what do I do? */
  10901.         return;
  10902.     }
  10903.     encivec_o.data = encivec_i.data + encivec_i.length;
  10904.  
  10905.     /* is there a better way to initialize this? */
  10906.     memset(encivec_i.data, am_client, blocksize);
  10907.     memset(encivec_o.data, 1 - am_client, blocksize);
  10908. }
  10909. #endif /* MIT_CURRENT */
  10910.  
  10911.  
  10912. int
  10913. #ifdef CK_ANSIC
  10914. ck_krb_rlogin(CHAR * hostname, int port,
  10915.                CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
  10916.                struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
  10917.                int kversion, int encrypt_flag)
  10918. #else /* CK_ANSIC */
  10919. ck_krb_rlogin(hostname, port,
  10920.                localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
  10921.     CHAR * hostname; int port;
  10922.     CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
  10923.     struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
  10924.     int kversion; int encrypt_flag;
  10925. #endif /* CK_ANSIC */
  10926. {
  10927.     unsigned long status;
  10928.     char * realm=NULL;
  10929.     extern int ttyfd;
  10930.     int c;
  10931.     long msglen;
  10932.  
  10933.     debug(F111,"ck_krb_rlogin",hostname,port);
  10934.  
  10935.     if ( kversion == 4 && !ck_krb4_is_installed() ) {
  10936.         printf("?Kerberos 4 is not installed\r\n");
  10937.         return(-1);
  10938.     } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
  10939.         printf("?Kerberos 5 is not installed\r\n");
  10940.         return(-1);
  10941.     }
  10942.  
  10943.     if ( encrypt_flag && !ck_crypt_is_installed() ) {
  10944.         printf("?Encryption is not installed\r\n");
  10945.         return(-1);
  10946.     }
  10947.  
  10948.     if ( kversion == 5 ) {
  10949. #ifdef KRB5
  10950.         krb5_flags authopts=0;
  10951.         krb5_ccache ccache=NULL;
  10952.         char *cksumbuf=NULL;
  10953.         char *service=NULL;
  10954.         krb5_data cksumdat;
  10955.         krb5_creds *get_cred = 0;
  10956.         krb5_error_code status;
  10957.         krb5_error      *error = 0;
  10958.         krb5_ap_rep_enc_part *rep_ret = NULL;
  10959.         krb5_data outbuf;
  10960.         int rc;
  10961.         krb5_int32 seqno=0;
  10962.         krb5_int32 server_seqno=0;
  10963.         char ** realmlist=NULL;
  10964.         int buflen;
  10965.  
  10966.         debug(F100,"ck_krb_rlogin version 5","",0);
  10967.  
  10968.         buflen = strlen(term_speed)+strlen(remoteuser)+64;
  10969.         if ((cksumbuf = malloc(buflen)) == 0)
  10970.           {
  10971.               printf("Unable to allocate memory for checksum buffer.\r\n");
  10972.               return(-1);
  10973.           }
  10974.  
  10975.         ckmakmsg(cksumbuf,buflen,ckuitoa((unsigned short) ntohs(port)),
  10976.                   term_speed,remoteuser,NULL);
  10977.         cksumdat.data = cksumbuf;
  10978.         cksumdat.length = strlen(cksumbuf);
  10979.  
  10980.         status = krb5_init_context(&k5_context);
  10981.         if (status) {
  10982.             debug(F110,"ck_krb_rlogin()","unable to init_context",0);
  10983.             return(-1);
  10984.         }
  10985.  
  10986.         desinbuf.data = des_inbuf;
  10987.         desoutbuf.data = des_outpkt+4;  /* Set up des buffers */
  10988.  
  10989.         rc = k5_get_ccache(k5_context,&ccache,NULL);
  10990.         if (rc != 0) {
  10991.             com_err(NULL, rc, "while getting ccache.");
  10992.             return(0);
  10993.         }
  10994.  
  10995.         service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
  10996.  
  10997.         if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
  10998.             printf("ck_krb_rlogin: no memory\r\n");
  10999.             return(-1);
  11000.         }
  11001.         status = krb5_sname_to_principal(k5_context, hostname, service,
  11002.                                           KRB5_NT_SRV_HST, &get_cred->server);
  11003.         if (status) {
  11004.             printf("ck_krb_rlogin: krb5_sname_to_principal failed: %s\r\n",
  11005.                      error_message(status));
  11006.             return(-1);
  11007.         }
  11008.  
  11009.         krb5_get_host_realm(k5_context,hostname,&realmlist);
  11010.         if (realmlist && realmlist[0]) {
  11011.             makestr(&realm,realmlist[0]);
  11012.             krb5_free_host_realm(k5_context,realmlist);
  11013.             realmlist = NULL;
  11014.         }
  11015.         if (!realm || !realm[0] )
  11016.             realm = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  11017.         if (realm && *realm) {
  11018.             free(krb5_princ_realm(k5_context,get_cred->server)->data);
  11019.             krb5_princ_set_realm_length(k5_context,
  11020.                                         get_cred->server,
  11021.                                         strlen(realm)
  11022.                                         );
  11023.             krb5_princ_set_realm_data(k5_context,
  11024.                                       get_cred->server,
  11025.                                       strdup(realm)
  11026.                                       );
  11027.         }
  11028.  
  11029.         ttoc(0);
  11030.  
  11031.         if (status = krb5_cc_get_principal(k5_context,
  11032.                                            ccache,
  11033.                                            &get_cred->client)
  11034.             ) {
  11035.             (void) krb5_cc_close(k5_context, ccache);
  11036.             krb5_free_creds(k5_context, get_cred);
  11037.             goto bad;
  11038.         }
  11039.  
  11040.         /* Get ticket from credentials cache or kdc */
  11041.         status = krb5_get_credentials(k5_context,
  11042.                                       0,
  11043.                                       ccache,
  11044.                                       get_cred,
  11045.                                       &ret_cred
  11046.                                       );
  11047.         krb5_free_creds(k5_context, get_cred);
  11048.         get_cred = NULL;
  11049.         (void) krb5_cc_close(k5_context, ccache);
  11050.  
  11051.         if (status)
  11052.             goto bad;
  11053.  
  11054.         authopts = AP_OPTS_MUTUAL_REQUIRED;
  11055.         {
  11056.             krb5_boolean similar;
  11057.  
  11058.             if (status = krb5_c_enctype_compare( k5_context,
  11059.                                                  ENCTYPE_DES_CBC_CRC,
  11060. #ifdef HEIMDAL
  11061.                                                  ret_cred->session.keytype,
  11062. #else /* HEIMDAL */
  11063.                                                  ret_cred->keyblock.enctype,
  11064. #endif /* HEIMDAL */
  11065.                                                  &similar)) {
  11066.                 krb5_free_creds(k5_context, ret_cred);
  11067.                 ret_cred = NULL;
  11068.                 return(-1);
  11069.             }
  11070.             if ( !similar )
  11071.                 authopts |= AP_OPTS_USE_SUBKEY;
  11072.         }
  11073.  
  11074.         if (krb5_auth_con_init(k5_context, &auth_context))
  11075.             goto bad;
  11076.  
  11077.         if (krb5_auth_con_setflags(k5_context, auth_context,
  11078.                                     KRB5_AUTH_CONTEXT_RET_TIME))
  11079.             goto bad;
  11080.  
  11081.         /* Only need local address for mk_cred() to send to krlogind */
  11082.         if (!krb5_d_no_addresses)
  11083.           if (status = krb5_auth_con_genaddrs(k5_context,
  11084.                                             auth_context,
  11085.                                             ttyfd,
  11086.                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
  11087.                                             )
  11088.             )
  11089.             goto bad;
  11090.  
  11091.         /* call Kerberos library routine to obtain an authenticator,
  11092.            pass it over the socket to the server, and obtain mutual
  11093.            authentication.
  11094.          */
  11095.         status = krb5_sendauth(k5_context,
  11096.                                &auth_context,
  11097.                                (krb5_pointer) &ttyfd,
  11098.                                "KCMDV0.1",
  11099.                                ret_cred->client,
  11100.                                ret_cred->server,
  11101.                                 authopts,
  11102.                                &cksumdat,
  11103.                                ret_cred,
  11104.                                0,
  11105.                                &error,
  11106.                                &rep_ret,
  11107.                                NULL
  11108.                                );
  11109.         krb5_free_data_contents(k5_context,&cksumdat);
  11110.  
  11111.         if (status) {
  11112.             printf("Couldn't authenticate to server: %s\r\n",
  11113.                      error_message(status));
  11114.             if (error) {
  11115.                 printf("Server returned error code %d (%s)\r\n",
  11116.                         error->error,
  11117.                         error_message(ERROR_TABLE_BASE_krb5 + error->error));
  11118.                 if (error->text.length) {
  11119.                     printf("Error text sent from server: %s\r\n",
  11120.                              error->text.data);
  11121.                 }
  11122.                 krb5_free_error(k5_context, error);
  11123.                 error = 0;
  11124.             }
  11125.             goto bad;
  11126.         }
  11127.  
  11128.         if (rep_ret) {
  11129.             server_seqno = rep_ret->seq_number;
  11130.             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
  11131.         }
  11132.  
  11133.         (void) ttol(remoteuser, strlen(remoteuser)+1);
  11134.         (void) ttol(term_speed, strlen(term_speed)+1);
  11135.         (void) ttol(localuser, strlen(localuser)+1);
  11136.  
  11137.         if (forward_flag) {   /* Forward credentials (global) */
  11138.             if (status = krb5_fwd_tgt_creds( k5_context,
  11139.                                              auth_context,
  11140.                                              hostname,
  11141.                                              ret_cred->client,
  11142.                                              ret_cred->server,
  11143.                                              0,
  11144.                                              (forwardable_flag ?
  11145.                                                OPTS_FORWARDABLE_CREDS :
  11146.                                                0),
  11147.                                              &outbuf
  11148.                                              )
  11149.                  )
  11150.             {
  11151.                 printf("Error forwarding credentials: %s\r\n",
  11152.                          error_message(status));
  11153.                 goto bad2;
  11154.             }
  11155.  
  11156.             /* Send forwarded credentials */
  11157. #ifndef COMMENT
  11158.             if (status = krb5_write_message(k5_context,
  11159.                                             (krb5_pointer)&ttyfd,
  11160.                                             &outbuf
  11161.                                             )
  11162.                 )
  11163.                 goto bad;
  11164. #else /* COMMENT */
  11165.             msglen = htonl(outbuf.length);
  11166.             if (ttol((CHAR *)&msglen,4) != 4) {
  11167.                 status = -1;
  11168.                 goto bad;
  11169.             }
  11170.             if ( outbuf.length ) {
  11171.                 if (ttol(outbuf.data,outbuf.length) != outbuf.length) {
  11172.                     status = -1;
  11173.                     goto bad;
  11174.                 }
  11175.             }
  11176. #endif /* COMMENT */
  11177.         }
  11178.         else { /* Dummy write to signal no forwarding */
  11179.           bad2:
  11180. #ifndef COMMENT
  11181.             outbuf.length = 0;
  11182.             if (status = krb5_write_message(k5_context,
  11183.                                             (krb5_pointer)&ttyfd,
  11184.                                             &outbuf
  11185.                                             )
  11186.                 )
  11187.                 goto bad;
  11188. #else /* COMMENT */
  11189.             msglen = htonl(0);
  11190.             if (ttol((CHAR *)&msglen,4) != 4) {
  11191.                 status = -1;
  11192.                 goto bad;
  11193.             }
  11194. #endif /* COMMENT */
  11195.         }
  11196.  
  11197.         if ((c = ttinc(0)) < 0) {
  11198.             if (c==-1) {
  11199.                 perror(hostname);
  11200.             } else {
  11201.                 printf("ck_krb_rlogin: bad connection with remote host\r\n");
  11202.             }
  11203.             status = -1;
  11204.             goto bad;
  11205.         }
  11206.         if (c != 0) {
  11207.             while ((c = ttinc(1)) >= 0) {
  11208.                 (void) printf("%c",c);
  11209.                 if (c == '\n')
  11210.                     break;
  11211.             }
  11212.             status = -1;
  11213.             goto bad;
  11214.         }
  11215.  
  11216. #ifdef MIT_CURRENT
  11217.         /* This code comes from the new MIT krb-current sources which is not */
  11218.         /* supported in the krb-1.0.5 distribution upon which all of the     */
  11219.         /* shipping libraries are based.                                     */
  11220.  
  11221.         if ( status == 0 ) {        /* success */
  11222.             krb5_boolean similar;
  11223.             krb5_keyblock * key = 0;
  11224.  
  11225.             if (status = krb5_c_enctype_compare( k5_context,
  11226.                                                  ENCTYPE_DES_CBC_CRC,
  11227. #ifdef HEIMDAL
  11228.                                                  ret_cred->session.keytype,
  11229. #else /* HEIMDAL */
  11230.                                                  ret_cred->keyblock.enctype,
  11231. #endif /* HEIMDAL */
  11232.                                                  &similar)) {
  11233.                 krb5_free_creds(k5_context, ret_cred);
  11234.                 ret_cred = NULL;
  11235.                 return(-1);
  11236.             }
  11237.  
  11238.             /* what is do_inband for? */
  11239.             /* do_inband = !similar; */
  11240.             if ( !similar ) {
  11241.  
  11242.                 status = krb5_auth_con_getlocalsubkey( k5_context,
  11243.                                                        auth_context,
  11244.                                                        &key);
  11245.                 if ((status || !key) && encrypt_flag )
  11246.                     goto bad;
  11247.             }
  11248.             if ( key == 0 ) {
  11249. #ifdef HEIMDAL
  11250.                 key = &ret_cred->session;
  11251. #else /* HEIMDAL */
  11252.                 key = &ret_cred->keyblock;
  11253. #endif /* HEIMDAL */
  11254.             }
  11255.  
  11256.             rcmd_stream_init_krb5(key, encrypt_flag, 1);
  11257.             if ( encrypt_flag )
  11258.                 rlog_encrypt = 1;
  11259.         }
  11260. #else /* OLD_MIT_RLOGIN */
  11261.         if ( status ) {
  11262.             /* should check for KDC_PR_UNKNOWN, NO_TKT_FILE here -- XXX */
  11263.             if (status != -1)
  11264.                 printf("[e]klogin to host %s failed - %s\r\n",hostname,
  11265.                          error_message(status));
  11266.             goto bad;
  11267.         }
  11268.  
  11269.         if ( encrypt_flag ) {
  11270.             /* if we are encrypting we need to setup the encryption */
  11271.             /* routines.  setup eblock for des_read and write       */
  11272. #ifdef HEIMDAL
  11273.             krb5_use_enctype(k5_context, &eblock,
  11274.                               ret_cred->session.keytype
  11275.                               );
  11276. #else /* HEIMDAL */
  11277.             krb5_use_enctype(k5_context, &eblock,
  11278.                               ret_cred->keyblock.enctype
  11279.                               );
  11280. #endif /* HEIMDAL */
  11281. #ifdef HEIMDAL
  11282.             status = krb5_process_key(k5_context,
  11283.                                        &eblock,
  11284.                                        &ret_cred->session
  11285.                                        );
  11286. #else /* HEIMDAL */
  11287.             status = krb5_process_key(k5_context,
  11288.                                        &eblock,
  11289.                                        &ret_cred->keyblock
  11290.                                        );
  11291. #endif /* HEIMDAL */
  11292.             if (status) {
  11293.                 printf("Cannot process session key : %s.\r\n",
  11294.                          error_message(status)
  11295.                          );
  11296.                 goto bad;
  11297.             }
  11298.             rlog_encrypt = 1;
  11299.         }
  11300.  
  11301. #endif /* OLD_MIT_RLOGIN */
  11302.         return (0);     /* success */
  11303.  
  11304.       bad:
  11305.         if (ret_cred) {
  11306.             krb5_free_creds(k5_context, ret_cred);
  11307.             ret_cred = NULL;
  11308.         }
  11309.         return (status);
  11310. #else /* KRB5 */
  11311.         return(-1);
  11312. #endif /* KRB5 */
  11313.     } else if (kversion == 4) {
  11314. #ifdef KRB4
  11315.         debug(F100,"ck_krb_rlogin version 4","",0);
  11316.  
  11317.         realm = (char *)krb_realmofhost(szHostName);
  11318.         if ((realm == NULL) || (realm[0] == '\0')) {
  11319.             realm = krb4_d_realm;
  11320.         }
  11321.  
  11322.         ttoc(0);        /* write a NUL */
  11323.  
  11324.         status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
  11325.                                ttyfd,
  11326.                                &k4_auth,
  11327.                                krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  11328.                                hostname,
  11329.                                realm,
  11330.                                (unsigned long) getpid(),
  11331.                                &k4_msg_data,
  11332.                                (CREDENTIALS *)&cred,
  11333. #ifdef CK_ENCRYPTION
  11334.                                &k4_sched,
  11335. #else /* ENCRYPTION */
  11336.                                NULL,
  11337. #endif /* ENCRYPTION */
  11338.                                l_addr,
  11339.                                r_addr,
  11340.                                "KCMDV0.1");
  11341.         debug(F111,"ck_krb_rlogin","krb_sendauth",status);
  11342.         if (status != KSUCCESS) {
  11343.             printf( "krb_sendauth failed: %s\r\n",
  11344.                     krb_get_err_text_entry(status)
  11345.                     );
  11346.             return(-1);
  11347.         }
  11348.         ttol(remoteuser,strlen(remoteuser)+1);
  11349.         ttol(term_speed,strlen(term_speed)+1);
  11350.  
  11351.       reread:
  11352.         if ((c = ttinc(0)) < 0) {
  11353.             printf("rcmd: bad connection with remote host\r\n");
  11354.             return(-1);
  11355.         }
  11356.         debug(F111,"ck_krb_rlogin","first byte",c);
  11357.  
  11358.         if (c != 0) {
  11359.             char *check = "ld.so: warning:";
  11360.             /* If rlogind was compiled on SunOS4, and it somehow
  11361.             got the shared library version numbers wrong, it
  11362.             may give an ld.so warning about an old version of a
  11363.             shared library.  Just ignore any such warning.
  11364.             Note that the warning is a characteristic of the
  11365.             server; we may not ourselves be running under
  11366.             SunOS4.  */
  11367.             if (c == 'l') {
  11368.                 char *p;
  11369.                 char cc;
  11370.  
  11371.                 p = &check[1];
  11372.                 while ((c = ttinc(0)) >= 0) {
  11373.                     if (*p == '\0') {
  11374.                         if (c == '\n')
  11375.                             break;
  11376.                     } else {
  11377.                         if (c != *p)
  11378.                             break;
  11379.                         ++p;
  11380.                     }
  11381.                 }
  11382.  
  11383.                 if (*p == '\0')
  11384.                     goto reread;
  11385.             }
  11386.  
  11387.             printf(check);
  11388.             while ((c = ttinc(1)) >= 0) {
  11389.                 printf("%c",c);
  11390.                 if (c == '\n')
  11391.                     break;
  11392.             }
  11393.             debug(F110,"ck_krb_rlogin","fatal error 1",0);
  11394.             return(-1);
  11395.         }
  11396.  
  11397. #ifdef CK_ENCRYPTION
  11398.         if ( encrypt_flag ) {
  11399.             /* if we are encrypting we need to setup the encryption */
  11400.             /* routines.                                            */
  11401.             des_key_sched(cred.session, k4_sched);
  11402.             rlog_encrypt = 1;
  11403.         }
  11404. #endif /* ENCRYPTION */
  11405. #else /* KRB4 */
  11406.         return(-1);
  11407. #endif /* KRB4 */
  11408.     }
  11409.     return(0); /* success */
  11410. }
  11411.  
  11412. #define SRAND   srand
  11413. #define RAND    rand
  11414. #define RAND_TYPE       int
  11415.  
  11416. static long
  11417. random_confounder(size, fillin)
  11418. size_t size;
  11419. char * fillin;
  11420. {
  11421.     static int seeded = 0;
  11422.     register unsigned char *real_fill;
  11423.     RAND_TYPE   rval;
  11424.  
  11425.     if (!seeded) {
  11426.         /* time() defined in 4.12.2.4, but returns a time_t, which is an
  11427.            "arithmetic type" (4.12.1) */
  11428.         rval = (RAND_TYPE) time(0);
  11429.         SRAND(rval);
  11430.         rval = RAND();
  11431.         rval ^= getpid();
  11432.         SRAND(rval);
  11433.         seeded = 1;
  11434.     }
  11435.  
  11436.     real_fill = (unsigned char *)fillin;
  11437.     while (size > 0) {
  11438.         rval = RAND();
  11439.         *real_fill = rval & 0xff;
  11440.         real_fill++;
  11441.         size--;
  11442.         if (size) {
  11443.             *real_fill = (rval >> 8) & 0xff;
  11444.             real_fill++;
  11445.             size--;
  11446.         }
  11447.     }
  11448.     return 0;
  11449. }
  11450.  
  11451. #ifdef KRB5
  11452. int
  11453. krb5_des_avail(fd)
  11454.     int fd;
  11455. {
  11456.     return(nstored);
  11457. }
  11458.  
  11459. int
  11460. krb5_des_read(fd, buf, len)
  11461.      int fd;
  11462.      register char *buf;
  11463.      int len;
  11464. {
  11465.     int nreturned = 0;
  11466.     long net_len,rd_len;
  11467.     int cc;
  11468.     unsigned char len_buf[4];
  11469.     krb5_error_code status;
  11470.     unsigned char c;
  11471.     int gotzero = 0;
  11472. #ifdef MIT_CURRENT
  11473.     krb5_data plain;
  11474.     krb5_enc_data cipher;
  11475. #endif /* MIT_CURRENT */
  11476.  
  11477.     debug(F111,"krb5_des_read","len",len);
  11478.     debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
  11479.     if ( !rlog_encrypt ) {
  11480.         cc = net_read(fd, buf, len);
  11481.         debug(F111,"krb5_des_read","chars read",cc);
  11482.         if ( cc < 0 )
  11483.             netclos();
  11484.         return(cc);
  11485.     }
  11486.  
  11487.     if (nstored >= len) {
  11488.         if ( buf ) {
  11489.             memcpy(buf, store_ptr, len);        /* safe */
  11490.             store_ptr += len;
  11491.             nstored -= len;
  11492.             return(len);
  11493.         } else
  11494.             return(0);
  11495.     } else if (nstored) {
  11496.         if ( buf ) {
  11497.             memcpy(buf, store_ptr, nstored);    /* safe */
  11498.             nreturned += nstored;
  11499.             buf += nstored;
  11500.             len -= nstored;
  11501.             nstored = 0;
  11502.         }
  11503.         else
  11504.             return(0);
  11505.     }
  11506.  
  11507.     /* See the comment in v4_des_read. */
  11508.     do {
  11509.         cc = net_read(fd, &c, 1);
  11510.         /* we should check for non-blocking here, but we'd have
  11511.         to make it save partial reads as well. */
  11512.         if (cc <= 0) {
  11513.             return cc; /* read error */
  11514.         }
  11515.         if (cc == 1) {
  11516.             if (c == 0) gotzero = 1;
  11517.         }
  11518.     } while (!gotzero);
  11519.  
  11520.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11521.     rd_len = c;
  11522.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11523.     rd_len = (rd_len << 8) | c;
  11524.     if ((cc = net_read(fd, &c, 1)) != 1) return 0;
  11525.     rd_len = (rd_len << 8) | c;
  11526.  
  11527. #ifdef MIT_CURRENT
  11528.     if (ret = krb5_c_encrypt_length(k5_context, k5_session_key->enctype,
  11529.                               rd_len, &net_len)) {
  11530.         errno = ret;
  11531.         return(-1);
  11532.     }
  11533. #else /* MIT_CURRENT */
  11534.     net_len = krb5_encrypt_size(rd_len, eblock.crypto_entry);
  11535. #endif /* MIT_CURRENT */
  11536.     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
  11537.         /* preposterous length; assume out-of-sync; only
  11538.            recourse is to close connection, so return 0 */
  11539.         printf("Read size problem.\r\n");
  11540.         return(0);
  11541.     }
  11542.     if ((cc = net_read(fd, desinbuf.data, net_len)) != net_len )
  11543.     {
  11544.         /* pipe must have closed, return 0 */
  11545.         printf( "Read error: length received %d != expected %d.\r\n",
  11546.                 cc,
  11547.                 net_len
  11548.                 );
  11549.         return(cc);
  11550.     }
  11551.     /* decrypt info */
  11552. #ifdef MIT_CURRENT
  11553.     cipher.enctype = ENCTYPE_UNKNOWN;
  11554.     cipher.ciphertext.length = net_len;
  11555.     cipher.ciphertext.data = desinbuf.data;
  11556.     plain.length = sizeof(storage);
  11557.     plain.data = storage;
  11558.  
  11559.     if ( status = krb5_c_decrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
  11560.                          encivec_i.length?&encivec_i:0,
  11561.                          &cipher,&plain) ) {
  11562.         /* probably out of sync */
  11563.         printf("Cannot decrypt data from network: %s\r\n",
  11564.                  error_message(status));
  11565.         errno = EIO;
  11566.         return(-1);
  11567.     }
  11568. #else /* MIT_CURRENT */
  11569.     if ((status = krb5_decrypt(k5_context, desinbuf.data,
  11570.                       (krb5_pointer) storage,
  11571.                       net_len,
  11572.                       &eblock, 0))) {
  11573.         printf("Cannot decrypt data from network: %s\r\n",
  11574.                  error_message(status));
  11575.         return(0);
  11576.     }
  11577. #endif /* MIT_CURRENT */
  11578.     store_ptr = storage;
  11579.     nstored = rd_len;
  11580.     if ( !buf ) {
  11581.         return(0);
  11582.     }
  11583.  
  11584.     if (nstored > len) {
  11585.         memcpy(buf, store_ptr, len);            /* safe */
  11586.         nreturned += len;
  11587.         store_ptr += len;
  11588.         nstored -= len;
  11589.     } else {
  11590.         memcpy(buf, store_ptr, nstored);        /* safe */
  11591.         nreturned += nstored;
  11592.         nstored = 0;
  11593.     }
  11594.     return(nreturned);
  11595. }
  11596.  
  11597. int
  11598. krb5_des_write(fd, buf, len)
  11599.      int fd;
  11600.      char *buf;
  11601.      int len;
  11602. {
  11603.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  11604.     int cc;
  11605.     krb5_error_code status;
  11606. #ifdef MIT_CURRENT
  11607.     krb5_data plain;
  11608.     krb5_enc_data cipher;
  11609. #endif /* MIT_CURRENT */
  11610.  
  11611.     debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
  11612.     if ( !rlog_encrypt ) {
  11613.         cc = net_write(fd, buf, len);
  11614.         debug(F111,"net_write","chars written",cc);
  11615.         return(cc != len ? -1 : len);
  11616.     }
  11617.  
  11618. #ifdef MIT_CURRENT
  11619.     plain.data = buf;
  11620.     plain.length = len;
  11621.  
  11622.     cipher.ciphertext.length = sizeof(des_outpkt)-4;
  11623.     cipher.ciphertext.data = desoutbuf.data;
  11624.  
  11625.     if ( status = krb5_c_encrypt(k5_context, k5_session_key, KCMD_KEYUSAGE,
  11626.                          encivec_o.length?&encivec_o:0,
  11627.                          &plain, &cipher)) {
  11628.         printf("Write encrypt problem: %s.\r\n",
  11629.                  error_message(status));
  11630.         errno = EIO;
  11631.         return(-1);
  11632.     }
  11633.     desoutbuf.length = cipher.ciphertext.length;
  11634. #else /* MIT_CURRENT */
  11635.     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
  11636.     if (desoutbuf.length > sizeof(des_outpkt)-4){
  11637.         printf("Write size problem.\r\n");
  11638.         return(-1);
  11639.     }
  11640.     if ((status = krb5_encrypt(k5_context, (krb5_pointer)buf,
  11641.                       desoutbuf.data,
  11642.                       len,
  11643.                       &eblock,
  11644.                       0))){
  11645.         printf("Write encrypt problem: %s.\r\n",
  11646.                  error_message(status));
  11647.         return(-1);
  11648.     }
  11649. #endif /* MIT_CURRENT */
  11650.  
  11651.     len_buf[0] = (len & 0xff000000) >> 24;
  11652.     len_buf[1] = (len & 0xff0000) >> 16;
  11653.     len_buf[2] = (len & 0xff00) >> 8;
  11654.     len_buf[3] = (len & 0xff);
  11655.  
  11656.     if (net_write(fd, des_outpkt,desoutbuf.length+4)
  11657.          != desoutbuf.length+4){
  11658.         printf("Could not write out all data\r\n");
  11659.         return(-1);
  11660.     }
  11661.     else return(len);
  11662. }
  11663. #endif /* KRB5 */
  11664.  
  11665. #ifdef KRB4
  11666. /*
  11667.  * Note that the encrypted rlogin packets take the form of a four-byte
  11668.  * length followed by encrypted data.  On writing the data out, a significant
  11669.  * performance penalty is suffered (at least one RTT per character, two if we
  11670.  * are waiting for a shell to echo) by writing the data separately from the
  11671.  * length.  So, unlike the input buffer, which just contains the output
  11672.  * data, the output buffer represents the entire packet.
  11673.  */
  11674.  
  11675. int
  11676. krb4_des_avail(fd)
  11677.     int fd;
  11678. {
  11679.     return(nstored);
  11680. }
  11681.  
  11682. int
  11683. krb4_des_read(fd, buf, len)
  11684. int fd;
  11685. register char *buf;
  11686. int len;
  11687. {
  11688.     int nreturned = 0;
  11689.     unsigned long net_len, rd_len;
  11690.     int cc;
  11691.     unsigned char c;
  11692.     int gotzero = 0;
  11693.  
  11694.     debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
  11695.     debug(F111,"krb4_des_read","len",len);
  11696.     if ( !rlog_encrypt ) {
  11697.         cc = net_read(fd, buf, len);
  11698.         debug(F111,"krb4_des_read","chars read",cc);
  11699.         if ( cc < 0 )
  11700.             netclos();
  11701.         return(cc);
  11702.     }
  11703.  
  11704.     if (nstored >= len) {
  11705.         if ( buf ) {
  11706.             debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
  11707.             memcpy(buf, store_ptr, len);        /* safe */
  11708.             store_ptr += len;
  11709.             nstored -= len;
  11710.             return(len);
  11711.         } else
  11712.             return(0);
  11713.     } else if (nstored) {
  11714.         if ( buf ) {
  11715.             debug(F111,"krb4_des_read (nstored)","nstored",nstored);
  11716.             memcpy(buf, store_ptr, nstored);    /* safe */
  11717.             nreturned += nstored;
  11718.             buf += nstored;
  11719.             len -= nstored;
  11720.             nstored = 0;
  11721.         } else
  11722.             return(0);
  11723.     }
  11724.  
  11725.     /* We're fetching the length which is MSB first, and the MSB
  11726.     has to be zero unless the client is sending more than 2^24
  11727.     (16M) bytes in a single write (which is why this code is in
  11728.     rlogin but not rcp or rsh.) The only reasons we'd get something
  11729.     other than zero are:
  11730.     -- corruption of the tcp stream (which will show up when
  11731.     everything else is out of sync too)
  11732.     -- un-caught Berkeley-style "pseudo out-of-band data" which
  11733.     happens any time the user hits ^C twice.
  11734.     The latter is *very* common, as shown by an 'rlogin -x -d'
  11735.     using the CNS V4 rlogin.         Mark EIchin 1/95
  11736.     */
  11737.     debug(F110,"krb4_des_read",
  11738.           "about to call net_read() this will block",
  11739.           0
  11740.           );
  11741.     do {
  11742.         cc = net_read(fd, &c, 1);
  11743.         debug(F111,"net_read","chars read",cc);
  11744.         if (cc <= 0) {
  11745.             netclos();
  11746.             return(-1);
  11747.         }
  11748.         if (cc != 1) return 0; /* read error */
  11749.         if (cc == 1) {
  11750.             if (c == 0) gotzero = 1;
  11751.         }
  11752.     } while (!gotzero);
  11753.  
  11754.     debug(F110,"krb4_des_read","gotzero",0);
  11755.     cc = net_read(fd, &c, 1);
  11756.     debug(F111,"net_read","chars read",cc);
  11757.     if (cc < 0) {
  11758.         netclos();
  11759.         return(-1);
  11760.     } else if ( cc != 1 )
  11761.         return(0);
  11762.     net_len = c;
  11763.     cc = net_read(fd, &c, 1);
  11764.     debug(F111,"net_read","chars read",cc);
  11765.     if (cc < 0) {
  11766.         netclos();
  11767.         return(-1);
  11768.     } else if ( cc != 1 )
  11769.         return(0);
  11770.     net_len = (net_len << 8) | c;
  11771.     debug(F111,"net_read","chars read",cc);
  11772.     cc = net_read(fd, &c, 1);
  11773.     if (cc < 0) {
  11774.         netclos();
  11775.         return(-1);
  11776.     } else if ( cc != 1 )
  11777.         return(0);
  11778.     net_len = (net_len << 8) | c;
  11779.     debug(F111,"krb4_des_read","net_len",net_len);
  11780.  
  11781.     /* Note: net_len is unsigned */
  11782.     if (net_len > sizeof(des_inbuf)) {
  11783.         /* XXX preposterous length, probably out of sync.
  11784.         act as if pipe closed */
  11785.         return(0);
  11786.     }
  11787.     /* the writer tells us how much real data we are getting, but
  11788.     we need to read the pad bytes (8-byte boundary) */
  11789. #ifndef roundup
  11790. #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
  11791. #endif /* roundup */
  11792.     rd_len = roundup(net_len, 8);
  11793.     debug(F111,"krb4_des_read","rd_len",rd_len);
  11794.     cc = net_read(fd, des_inbuf, rd_len);
  11795.     debug(F111,"net_read","chars read",cc);
  11796.     if (cc < 0) {
  11797.         netclos();
  11798.         return(-1);
  11799.     } else if ( cc != rd_len )
  11800.         return(0);
  11801.  
  11802.     hexdump("krb4_des_read des_inbuf",des_inbuf,8);
  11803. #ifdef CK_ENCRYPTION
  11804. #ifdef KRB524
  11805.     (void) des_pcbc_encrypt(des_inbuf,
  11806.                              storage,
  11807.                              (net_len < 8) ? 8 : net_len,
  11808.                              k4_sched,
  11809.                              cred.session,
  11810.                              DECRYPT);
  11811. #else /* KRB524 */
  11812.     (void) des_pcbc_encrypt((Block *)des_inbuf,
  11813.                              (Block *)storage,
  11814.                              (net_len < 8) ? 8 : net_len,
  11815.                              k4_sched,
  11816.                              &cred.session,
  11817.                              DECRYPT);
  11818. #endif /* KRB524 */
  11819. #endif /* ENCRYPTION */
  11820.     hexdump("krb4_des_read storage",storage,8);
  11821.  
  11822.     /*
  11823.     * when the cleartext block is < 8 bytes, it is "right-justified"
  11824.     * in the block, so we need to adjust the pointer to the data
  11825.     */
  11826.     if (net_len < 8)
  11827.         store_ptr = storage + 8 - net_len;
  11828.     else
  11829.         store_ptr = storage;
  11830.     nstored = net_len;
  11831.  
  11832.     if ( !buf )
  11833.         return(0);
  11834.  
  11835.     if (nstored > len) {
  11836.         memcpy(buf, store_ptr, len);            /* safe */
  11837.         nreturned += len;
  11838.         store_ptr += len;
  11839.         nstored -= len;
  11840.     } else {
  11841.         memcpy(buf, store_ptr, nstored);        /* safe */
  11842.         nreturned += nstored;
  11843.         nstored = 0;
  11844.     }
  11845.  
  11846.     debug(F111,"net_read","nreturned",nreturned);
  11847.     return(nreturned);
  11848. }
  11849.  
  11850. int
  11851. krb4_des_write(fd, buf, len)
  11852. int fd;
  11853. char *buf;
  11854. int len;
  11855. {
  11856.     static char garbage_buf[8];
  11857.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  11858.     int cc;
  11859.  
  11860.     debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
  11861.     if ( !rlog_encrypt ) {
  11862.         cc = net_write(fd, buf, len);
  11863.         debug(F111,"net_write","chars written",cc);
  11864.         return(cc);
  11865.     }
  11866.  
  11867.     /*
  11868.     * pcbc_encrypt outputs in 8-byte (64 bit) increments
  11869.     *
  11870.     * it zero-fills the cleartext to 8-byte padding,
  11871.     * so if we have cleartext of < 8 bytes, we want
  11872.     * to insert random garbage before it so that the ciphertext
  11873.     * differs for each transmission of the same cleartext.
  11874.     * if len < 8 - sizeof(long), sizeof(long) bytes of random
  11875.     * garbage should be sufficient; leave the rest as-is in the buffer.
  11876.     * if len > 8 - sizeof(long), just garbage fill the rest.
  11877.     */
  11878.     if (len < 8) {
  11879.         random_confounder(8 - len, garbage_buf);
  11880.         /* this "right-justifies" the data in the buffer */
  11881.         (void) memcpy(garbage_buf + 8 - len, buf, len); /* safe */
  11882.         hexdump("krb4_des_write garbage_buf",garbage_buf,8);
  11883.     } else
  11884.         hexdump("krb4_des_write buf",buf,8);
  11885. #ifdef CK_ENCRYPTION
  11886. #ifdef KRB524
  11887.     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
  11888.                              des_outpkt+4,
  11889.                              (len < 8) ? 8 : len,
  11890.                              k4_sched,
  11891.                              cred.session,
  11892.                              ENCRYPT);
  11893. #else /* KRB524 */
  11894.     (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
  11895.                              (Block *)(des_outpkt+4),
  11896.                              (len < 8) ? 8 : len,
  11897.                              k4_sched,
  11898.                              &cred.session,
  11899.                              ENCRYPT);
  11900. #endif /* KRB524 */
  11901. #endif /* ENCRYPTION */
  11902.     if ( len < 8 )
  11903.         hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
  11904.     else
  11905.         hexdump("krb4_des_write (post pcbc) buf",buf,8);
  11906.     hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
  11907.  
  11908.     /* tell the other end the real amount, but send an 8-byte padded
  11909.     packet */
  11910.     len_buf[0] = (len & 0xff000000) >> 24;
  11911.     len_buf[1] = (len & 0xff0000) >> 16;
  11912.     len_buf[2] = (len & 0xff00) >> 8;
  11913.     len_buf[3] = (len & 0xff);
  11914.     hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
  11915.     cc = net_write(fd, des_outpkt, roundup(len,8)+4);
  11916.     debug(F111,"net_write","chars written",cc);
  11917.     return(len);
  11918. }
  11919. #endif /* KRB4 */
  11920. #endif /* RLOGCODE */
  11921.  
  11922. #ifdef KRB524
  11923. #ifndef OS2
  11924. /* The following functions are missing from the compatibility library */
  11925. const char *
  11926. krb_get_err_text_entry(r) int r;
  11927. {
  11928.     extern char krb_err_text[];
  11929.     return(krb_err_txt[r]);
  11930. }
  11931. #endif /* OS2 */
  11932. #endif /* KRB524 */
  11933. #endif /* CK_KERBEROS */
  11934.  
  11935. #ifdef CK_KERBEROS
  11936. #ifdef KRB5_U2U
  11937. /* Kerberos 5 User to User Client */
  11938. int
  11939. k5_user_to_user_client_auth()
  11940. {
  11941.     extern int ttyfd;
  11942.     register int retval, i;
  11943.     char **srealms;             /* realm(s) of server */
  11944.     char *princ;                /* principal in credentials cache */
  11945.     krb5_ccache cc;
  11946.     krb5_creds creds, *new_creds;
  11947.     krb5_data reply, msg, msgtext, princ_data;
  11948.     krb5_ticket * ticket = NULL;
  11949.  
  11950.     if (retval = k5_get_ccache(k5_context,&cc,NULL))
  11951.     {
  11952.         com_err("uu-client", retval, "getting credentials cache");
  11953.         return(-1);
  11954.     }
  11955.  
  11956.     memset ((char*)&creds, 0, sizeof(creds));
  11957.     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
  11958.     {
  11959.         com_err("uu-client", retval, "getting principal name");
  11960.         return(-1);
  11961.     }
  11962.  
  11963.     if (retval = krb5_get_host_realm(k5_context, szHostName, &srealms))
  11964.     {
  11965.         com_err("uu-client", retval, "getting realms for \"%s\"", szHostName);
  11966.         return(-1);
  11967.     }
  11968.  
  11969.     if (retval = krb5_build_principal_ext(k5_context, &creds.server,
  11970.                                           krb5_princ_realm(k5_context,
  11971.                                                          creds.client)->length,
  11972.                                           krb5_princ_realm(k5_context,
  11973.                                                          creds.client)->data,
  11974.                                           6, "krbtgt",
  11975.                                           krb5_princ_realm(k5_context,
  11976.                                                          creds.client)->length,
  11977.                                           krb5_princ_realm(k5_context,
  11978.                                                          creds.client)->data,
  11979.                                           0))
  11980.     {
  11981.         com_err("uu-client", retval, "setting up tgt server name");
  11982.         return(-1);
  11983.     }
  11984.  
  11985.     /* Get TGT from credentials cache */
  11986.     if (retval = krb5_get_credentials(k5_context, KRB5_GC_CACHED, cc,
  11987.                                        &creds, &new_creds))
  11988.     {
  11989.         com_err("uu-client", retval, "getting TGT");
  11990.         return(-1);
  11991.     }
  11992.  
  11993.     if (retval = krb5_unparse_name(k5_context, creds.client, &princ)) {
  11994.         com_err("uu-client", retval, "printing principal name");
  11995.         return(-1);
  11996.     }
  11997.     i = strlen(princ) + 1;
  11998.     princ_data.data = princ;
  11999.     princ_data.length = i;              /* include null terminator for
  12000.                                            server's convenience */
  12001.     retval = krb5_write_message(k5_context,
  12002.                                 (krb5_pointer) &ttyfd, &princ_data);
  12003.     if (retval)
  12004.     {
  12005.         com_err("uu-client", retval, "sending principal name to server");
  12006.         return(-1);
  12007.     }
  12008.     krb5_free_unparsed_name(k5_context,princ);
  12009.  
  12010.     retval = krb5_write_message(k5_context,
  12011.                                 (krb5_pointer) &ttyfd, &new_creds->ticket);
  12012.     if (retval)
  12013.     {
  12014.         com_err("uu-client", retval, "sending ticket to server");
  12015.         return(-1);
  12016.     }
  12017.  
  12018.     retval = krb5_read_message(k5_context, (krb5_pointer) &ttyfd, &reply);
  12019.     if (retval)
  12020.     {
  12021.         com_err("uu-client", retval, "reading reply from server");
  12022.         return(-1);
  12023.     }
  12024.  
  12025.     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
  12026.         com_err("uu-client", retval, "initializing the auth_context");
  12027.         return(-1);
  12028.     }
  12029.  
  12030.     if (!krb5_d_no_addresses) {
  12031.       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  12032.                         KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
  12033.                         KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
  12034.         com_err("uu-client", retval, "generating addrs for auth_context");
  12035.         return(-1);
  12036.       }
  12037.     }
  12038.  
  12039.     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
  12040.                                         KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
  12041.         com_err("uu-client", retval, "initializing the auth_context flags");
  12042.         return(-1);
  12043.     }
  12044.  
  12045.     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
  12046.                                               &new_creds->keyblock)) {
  12047.         com_err("uu-client", retval, "setting useruserkey for authcontext");
  12048.         return(-1);
  12049.     }
  12050.  
  12051.     /* read the ap_req to get the session key */
  12052.     retval = krb5_rd_req(k5_context, &auth_context, &reply,
  12053.                           NULL, NULL, NULL, &ticket);
  12054.     if (retval) {
  12055.         com_err("uu-client", retval, "reading AP_REQ from server");
  12056.         return(-1);
  12057.     }
  12058.  
  12059.     if (k5_u2u_read_msg(k5_context,&msg) < 0)
  12060.         return(-1);
  12061.  
  12062.     if ( strcmp("Kermit implements Kerberos 5 User to User",msg.data) )
  12063.         return(-1);
  12064.     krb5_free_data_contents(k5_context,&msg);
  12065.  
  12066.     msgtext.data = "As do I! :-)";
  12067.     msgtext.length = strlen(msgtext.data)+1;
  12068.  
  12069.     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
  12070.         return(-1);
  12071.  
  12072.     if (retval = krb5_unparse_name(k5_context,
  12073. #ifdef HEIMDAL
  12074.                                     ticket->client,
  12075. #else /* HEIMDAL */
  12076.                                     ticket->enc_part2->client,
  12077. #endif /* HEIMDAL */
  12078.                                     &princ))
  12079.         com_err("uu-client", retval, "while unparsing client name");
  12080.     else {
  12081.         ckstrncpy(szUserNameAuthenticated,princ,UIDBUFLEN);
  12082.         validUser = AUTH_VALID;
  12083.         authentication_version = AUTHTYPE_KERBEROS_V5;
  12084.         if ( !quiet )
  12085.             printf("Peer name is \"%s\"\n", princ);
  12086.         krb5_free_unparsed_name(k5_context,princ);
  12087.     }
  12088.     return 0;
  12089. }
  12090.  
  12091. /* Kerberos 5 User to User Server */
  12092.  
  12093. int
  12094. k5_user_to_user_server_auth()
  12095. {
  12096.     krb5_data pname_data, tkt_data;
  12097.     int retval;
  12098.     krb5_creds creds, *new_creds;
  12099.     krb5_ccache cc;
  12100.     krb5_data msg, msgtext;
  12101.     extern int ttyfd;
  12102.  
  12103.     if (retval = krb5_read_message(k5_context,
  12104.                                    (krb5_pointer) &ttyfd, &pname_data)) {
  12105.         com_err ("uu-server", retval, "reading pname");
  12106.         return(-1);
  12107.     }
  12108.     /* client sends it already null-terminated. */
  12109.     if ( !quiet )
  12110.         printf ("Peer name is \"%s\".\n", pname_data.data);
  12111.     ckstrncpy(szUserNameAuthenticated,pname_data.data,UIDBUFLEN);
  12112.     validUser = AUTH_VALID;
  12113.     authentication_version = AUTHTYPE_KERBEROS_V5;
  12114.  
  12115.     if (retval = krb5_read_message(k5_context,
  12116.                                    (krb5_pointer) &ttyfd, &tkt_data)) {
  12117.         com_err ("uu-server", retval, "reading ticket data");
  12118.         return(-1);
  12119.     }
  12120.  
  12121.     if (retval = k5_get_ccache(k5_context,&cc,NULL))
  12122.     {
  12123.         com_err("uu-server", retval, "getting credentials cache");
  12124.         return(-1);
  12125.     }
  12126.  
  12127.     memset ((char*)&creds, 0, sizeof(creds));
  12128.     if (retval = krb5_cc_get_principal(k5_context, cc, &creds.client))
  12129.     {
  12130.         com_err("uu-server", retval, "getting principal name");
  12131.         return(-1);
  12132.     }
  12133.  
  12134.     if (retval = krb5_parse_name(k5_context, pname_data.data, &creds.server))
  12135.     {
  12136.         com_err("uu-server", retval, "parsing client name");
  12137.         return(-1);
  12138.     }
  12139.     creds.second_ticket = tkt_data;
  12140.  
  12141.     if (retval = krb5_get_credentials(k5_context, KRB5_GC_USER_USER,
  12142.                                        cc, &creds, &new_creds))
  12143.     {
  12144.         com_err("uu-server", retval, "getting user-user ticket");
  12145.         return(-1);
  12146.     }
  12147.  
  12148.     /* send a ticket/authenticator to the other side, so it can get the key
  12149.        we're using for the krb_safe below. */
  12150.  
  12151.     if (retval = krb5_auth_con_init(k5_context, &auth_context)) {
  12152.         com_err("uu-server", retval, "making auth_context");
  12153.         return(-1);
  12154.     }
  12155.  
  12156.     if (retval = krb5_auth_con_setflags(k5_context, auth_context,
  12157.                                          KRB5_AUTH_CONTEXT_DO_SEQUENCE)) {
  12158.         com_err("uu-server", retval, "initializing the auth_context flags");
  12159.         return(-1);
  12160.     }
  12161.  
  12162.     if (!krb5_d_no_addresses) {
  12163.       if (retval = krb5_auth_con_genaddrs(k5_context, auth_context, ttyfd,
  12164.                                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR |
  12165.                                 KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) {
  12166.         com_err("uu-server", retval, "generating addrs for auth_context");
  12167.         return(-1);
  12168.       }
  12169.     }
  12170.  
  12171.     if (retval = krb5_auth_con_setuseruserkey(k5_context, auth_context,
  12172.                                               &new_creds->keyblock)) {
  12173.         com_err("uu-server", retval, "setting useruserkey for authcontext");
  12174.         return(-1);
  12175.     }
  12176.  
  12177.     if (retval = krb5_mk_req_extended(k5_context, &auth_context,
  12178.                                       AP_OPTS_USE_SESSION_KEY |
  12179.                                       AP_OPTS_MUTUAL_REQUIRED,
  12180.                                       NULL, new_creds, &msg)) {
  12181.         com_err("uu-server", retval, "making AP_REQ");
  12182.         return(-1);
  12183.     }
  12184.     retval = krb5_write_message(k5_context, (krb5_pointer) &ttyfd, &msg);
  12185.     if (retval) {
  12186.         com_err("uu-server", retval, "writing message to client");
  12187.         return(-1);
  12188.     }
  12189.     krb5_free_data_contents(k5_context,&msg);
  12190.  
  12191.     msgtext.data = "Kermit implements Kerberos 5 User to User";
  12192.     msgtext.length = strlen(msgtext.data)+1;
  12193.  
  12194.     if (k5_u2u_write_msg(k5_context,&msgtext) < 0)
  12195.         return(-1);
  12196.  
  12197.     if (k5_u2u_read_msg(k5_context,&msg) < 0)
  12198.         return(-1);
  12199.  
  12200.     if ( strcmp("As do I! :-)",msg.data) )
  12201.         return(-1);
  12202.     krb5_free_data_contents(k5_context,&msg);
  12203.  
  12204.  
  12205.     return(0);
  12206. }
  12207.  
  12208. int
  12209. k5_u2u_read_msg(krb5_context context, int fd, krb5_data * msg)
  12210. {
  12211.     int retval;
  12212.     krb5_data reply;
  12213.  
  12214.     retval = krb5_read_message(context, (krb5_pointer) &fd, &reply);
  12215.     if (retval)
  12216.     {
  12217.         com_err("uu-client", retval, "reading reply");
  12218.         return(-1);
  12219.     }
  12220.  
  12221.     if (retval = krb5_rd_priv(context, auth_context, &reply, msg, NULL)) {
  12222.         com_err("uu-client", retval, "decoding reply");
  12223.         return(-1);
  12224.     }
  12225.     return(0);
  12226. }
  12227.  
  12228. int
  12229. k5_u2u_write_msg(krb5_context context, int fd, krb5_data * msgtext)
  12230. {
  12231.     int retval;
  12232.     krb5_data msg;
  12233.  
  12234.     if (retval = krb5_mk_priv(k5_context, auth_context, msgtext, &msg, NULL))
  12235.     {
  12236.         com_err("uu-server", retval, "encoding message");
  12237.         return(-1);
  12238.     }
  12239.  
  12240.     retval = krb5_write_message(k5_context, (krb5_pointer) &fd, &msg);
  12241.     krb5_free_data_contents(k5_context,&msg);
  12242.     if (retval)
  12243.     {
  12244.         com_err("uu-server", retval, "writing message");
  12245.         return(-1);
  12246.     }
  12247.     return(0);
  12248. }
  12249.  
  12250. int
  12251. krb5_u2u_avail(fd)
  12252.     int fd;
  12253. {
  12254.     return(nstored);
  12255. }
  12256.  
  12257. int
  12258. krb5_u2u_read(fd, buf, len)
  12259.      int fd;
  12260.      register char *buf;
  12261.      int len;
  12262. {
  12263.     int nreturned = 0;
  12264.     krb5_data msg;
  12265.  
  12266.     debug(F111,"krb5_u2u_read","len",len);
  12267.  
  12268.     if ( !buf )
  12269.         return(0);
  12270.  
  12271.     if (nstored >= len) {
  12272.         memcpy(buf, store_ptr, len);        /* safe */
  12273.         store_ptr += len;
  12274.         nstored -= len;
  12275.         return(len);
  12276.     } else if (nstored) {
  12277.         memcpy(buf, store_ptr, nstored);    /* safe */
  12278.         nreturned += nstored;
  12279.         buf += nstored;
  12280.         len -= nstored;
  12281.         nstored = 0;
  12282.     }
  12283.  
  12284.     if (k5_u2u_read_msg(k5_context, fd, &msg) < 0)
  12285.         return(-1);
  12286.  
  12287.     if ( msg.length <= len ) {
  12288.         memcpy(buf, msg.data, msg.length);
  12289.         nreturned += msg.length;
  12290.         nstored = 0;
  12291.     } else {
  12292.         memcpy(buf, msg.data, len);
  12293.         nreturned += len;
  12294.  
  12295.         if ( msg.length - len < sizeof(storage) ) {
  12296.             store_ptr = storage;
  12297.             nstored = msg.length - len;
  12298.             memcpy(storage,msg.data+len,nstored);
  12299.         } else {
  12300.             nstored = 0;
  12301.             return(-1);
  12302.         }
  12303.     }
  12304.     return(nreturned);
  12305. }
  12306.  
  12307. int
  12308. krb5_u2u_write(fd, buf, len)
  12309.      int fd;
  12310.      char *buf;
  12311.      int len;
  12312. {
  12313.     krb5_data msg;
  12314.  
  12315.     msg.length = len;
  12316.     msg.data = buf;
  12317.  
  12318.     if ( k5_u2u_write_msg(k5_context, fd, &msg) < 0 )
  12319.         return(-1);
  12320.     else
  12321.         return(len);
  12322. }
  12323.  
  12324. #endif /* KRB5_U2U */
  12325. #endif /* CK_KERBEROS */
  12326.  
  12327. #ifdef CK_FORWARD_X
  12328. /*
  12329.  
  12330. Copyright (c) 1988  X Consortium
  12331.  
  12332. Permission is hereby granted, free of charge, to any person obtaining a copy
  12333. of this software and associated documentation files (the "Software"), to deal
  12334. in the Software without restriction, including without limitation the rights
  12335. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12336. copies of the Software, and to permit persons to whom the Software is
  12337. furnished to do so, subject to the following conditions:
  12338.  
  12339. The above copyright notice and this permission notice shall be included in
  12340. all copies or substantial portions of the Software.
  12341.  
  12342. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12343. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12344. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
  12345. X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  12346. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  12347. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  12348.  
  12349. Except as contained in this notice, the name of the X Consortium shall not be
  12350. used in advertising or otherwise to promote the sale, use or other dealings
  12351. in this Software without prior written authorization from the X Consortium.
  12352.  
  12353. */
  12354. /*  Modified for stand-alone compiling by
  12355.  *  Peter 'Luna' Runestig <peter@runestig.com>
  12356.  */
  12357.  
  12358. #include <stdlib.h>
  12359. #include <string.h>
  12360. #include <fcntl.h>
  12361. #include <sys/stat.h>
  12362. #include <errno.h>
  12363. #include <time.h>
  12364. #define Time_t time_t
  12365.  
  12366. void
  12367. XauDisposeAuth (auth)
  12368. Xauth   *auth;
  12369. {
  12370.     if (auth) {
  12371.         if (auth->address) (void) free (auth->address);
  12372.         if (auth->number) (void) free (auth->number);
  12373.         if (auth->name) (void) free (auth->name);
  12374.         if (auth->data) {
  12375.             (void) bzero (auth->data, auth->data_length);
  12376.             (void) free (auth->data);
  12377.         }
  12378.         free ((char *) auth);
  12379.     }
  12380.     return;
  12381. }
  12382.  
  12383. char *
  12384. XauFileName ()
  12385. {
  12386.     char *slashDotXauthority = "/.Xauthority";
  12387.     char    *name;
  12388.     static char *buf=NULL;
  12389.     static int  bsize=0;
  12390.     int     size, namelen;
  12391.     extern char * tn_fwdx_xauthority;
  12392.  
  12393.     if ( tn_fwdx_xauthority )
  12394.         return(tn_fwdx_xauthority);
  12395.  
  12396.     if (name = getenv ("XAUTHORITY"))
  12397.         return(name);
  12398.     name = zhome();
  12399.     if ( !name )
  12400.         return(NULL);
  12401.     namelen = strlen (name);
  12402.     size = namelen + strlen(slashDotXauthority) + 1;
  12403.     if (size > bsize) {
  12404.         if (buf)
  12405.             free (buf);
  12406.         buf = malloc ((unsigned) size);
  12407.         if (!buf)
  12408.             return 0;
  12409.         bsize = size;
  12410.     }
  12411.     ckstrncpy (buf, name, bsize);
  12412.     if ( name[namelen-1] != '/'
  12413. #ifdef OS2
  12414.          && name[namelen-1] != '\\'
  12415. #endif /* OS2 */
  12416.          )
  12417.         ckstrncat (buf, slashDotXauthority, bsize);
  12418.     else
  12419.         ckstrncat (buf, &slashDotXauthority[1], bsize);
  12420.     return(buf);
  12421. }
  12422.  
  12423. static int
  12424. binaryEqual (a, b, len)
  12425. register char   *a, *b;
  12426. register int    len;
  12427. {
  12428.     while (len--)
  12429.         if (*a++ != *b++)
  12430.             return 0;
  12431.     return 1;
  12432. }
  12433.  
  12434. #ifndef R_OK
  12435. #define R_OK 04
  12436. #endif /* R_OK */
  12437.  
  12438. Xauth *
  12439. XauGetAuthByAddr (family, address_length, address,
  12440.                           number_length, number,
  12441.                           name_length, name)
  12442. unsigned int    family;
  12443. unsigned int    address_length;
  12444. const char      *address;
  12445. unsigned int    number_length;
  12446. const char      *number;
  12447. unsigned int    name_length;
  12448. const char      *name;
  12449. {
  12450.     FILE    *auth_file;
  12451.     char    *auth_name;
  12452.     Xauth   *entry;
  12453.  
  12454.     auth_name = XauFileName();
  12455.     if (!auth_name)
  12456.         return 0;
  12457.     if (access (auth_name, R_OK) != 0)          /* checks REAL id */
  12458.         return 0;
  12459.     auth_file = fopen (auth_name, "rb");
  12460.     if (!auth_file)
  12461.         return 0;
  12462.     for (;;) {
  12463.         entry = XauReadAuth (auth_file);
  12464.         if (!entry)
  12465.             break;
  12466.         /*
  12467.          * Match when:
  12468.          *   either family or entry->family are FamilyWild or
  12469.          *    family and entry->family are the same
  12470.          *  and
  12471.          *   either address or entry->address are empty or
  12472.          *    address and entry->address are the same
  12473.          *  and
  12474.          *   either number or entry->number are empty or
  12475.          *    number and entry->number are the same
  12476.          *  and
  12477.          *   either name or entry->name are empty or
  12478.          *    name and entry->name are the same
  12479.          */
  12480.  
  12481. /*      if ((family == FamilyWild || entry->family == FamilyWild ||
  12482.              (entry->family == family &&
  12483.               address_length == entry->address_length &&
  12484.               binaryEqual (entry->address, address, (int)address_length))) &&
  12485.             (number_length == 0 || entry->number_length == 0 ||
  12486.              (number_length == entry->number_length &&
  12487.               binaryEqual (entry->number, number, (int)number_length))) &&
  12488.             (name_length == 0 || entry->name_length == 0 ||
  12489.              (entry->name_length == name_length &&
  12490.               binaryEqual (entry->name, name, (int)name_length)))) */
  12491.         /* the original matching code above doesn't seem to meet the matching
  12492.          * algorithm, it doesn't check if "address_length == 0 ||
  12493.          * entry->address_length == 0". / Luna 2000-02-09
  12494.          */
  12495.         if ((family == FamilyWild || entry->family == FamilyWild ||
  12496.               entry->family == family) &&
  12497.             (address_length == 0 || entry->address_length == 0 ||
  12498.               (address_length == entry->address_length &&
  12499.               binaryEqual (entry->address, address, (int)address_length))) &&
  12500.             (number_length == 0 || entry->number_length == 0 ||
  12501.              (number_length == entry->number_length &&
  12502.               binaryEqual (entry->number, number, (int)number_length))) &&
  12503.             (name_length == 0 || entry->name_length == 0 ||
  12504.              (entry->name_length == name_length &&
  12505.               binaryEqual (entry->name, name, (int)name_length))))
  12506.             break;
  12507.         XauDisposeAuth (entry);
  12508.     }
  12509.     (void) fclose (auth_file);
  12510.     return entry;
  12511. }
  12512.  
  12513. static int
  12514. read_short (shortp, file)
  12515. unsigned short  *shortp;
  12516. FILE            *file;
  12517. {
  12518.     unsigned char   file_short[2];
  12519.  
  12520.     if (fread ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
  12521.         return 0;
  12522.     *shortp = file_short[0] * 256 + file_short[1];
  12523.     return 1;
  12524. }
  12525.  
  12526. static int
  12527. read_counted_string (countp, stringp, file)
  12528. unsigned short  *countp;
  12529. char    **stringp;
  12530. FILE    *file;
  12531. {
  12532.     unsigned short  len;
  12533.     char            *data;
  12534.  
  12535.     if (read_short (&len, file) == 0)
  12536.         return 0;
  12537.     if (len == 0) {
  12538.         data = 0;
  12539.     } else {
  12540.         data = malloc ((unsigned) len);
  12541.         if (!data)
  12542.             return 0;
  12543.         if (fread (data, (int) sizeof (char), (int) len, file) != len) {
  12544.             bzero (data, len);
  12545.             free (data);
  12546.             return 0;
  12547.         }
  12548.     }
  12549.     *stringp = data;
  12550.     *countp = len;
  12551.     return 1;
  12552. }
  12553.  
  12554. Xauth *
  12555. XauReadAuth (auth_file)
  12556. FILE    *auth_file;
  12557. {
  12558.     Xauth   local;
  12559.     Xauth   *ret;
  12560.  
  12561.     if (read_short (&local.family, auth_file) == 0)
  12562.         return 0;
  12563.     if (read_counted_string (&local.address_length,
  12564.                              &local.address, auth_file) == 0)
  12565.         return 0;
  12566.     if (read_counted_string (&local.number_length,
  12567.                              &local.number, auth_file) == 0) {
  12568.         if (local.address) free (local.address);
  12569.         return 0;
  12570.     }
  12571.     if (read_counted_string (&local.name_length,
  12572.                              &local.name, auth_file) == 0) {
  12573.         if (local.address) free (local.address);
  12574.         if (local.number) free (local.number);
  12575.         return 0;
  12576.     }
  12577.     if (read_counted_string (&local.data_length,
  12578.                              &local.data, auth_file) == 0) {
  12579.         if (local.address) free (local.address);
  12580.         if (local.number) free (local.number);
  12581.         if (local.name) free (local.name);
  12582.         return 0;
  12583.     }
  12584.     ret = (Xauth *) malloc (sizeof (Xauth));
  12585.     if (!ret) {
  12586.         if (local.address) free (local.address);
  12587.         if (local.number) free (local.number);
  12588.         if (local.name) free (local.name);
  12589.         if (local.data) {
  12590.             bzero (local.data, local.data_length);
  12591.             free (local.data);
  12592.         }
  12593.         return 0;
  12594.     }
  12595.     *ret = local;
  12596.     return ret;
  12597. }
  12598.  
  12599. static int
  12600. write_short (s, file)
  12601. unsigned short  s;
  12602. FILE            *file;
  12603. {
  12604.     unsigned char   file_short[2];
  12605.  
  12606.     file_short[0] = (s & (unsigned)0xff00) >> 8;
  12607.     file_short[1] = s & 0xff;
  12608.     if (fwrite ((char *) file_short, (int) sizeof (file_short), 1, file) != 1)
  12609.         return 0;
  12610.     return 1;
  12611. }
  12612.  
  12613. static int
  12614. write_counted_string (count, string, file)
  12615. unsigned short  count;
  12616. char    *string;
  12617. FILE    *file;
  12618. {
  12619.     if (write_short (count, file) == 0)
  12620.         return 0;
  12621.     if (fwrite (string, (int) sizeof (char), (int) count, file) != count)
  12622.         return 0;
  12623.     return 1;
  12624. }
  12625.  
  12626. int
  12627. XauWriteAuth (auth_file, auth)
  12628. FILE    *auth_file;
  12629. Xauth   *auth;
  12630. {
  12631.     if (write_short (auth->family, auth_file) == 0)
  12632.         return 0;
  12633.     if (write_counted_string (auth->address_length,
  12634.                               auth->address, auth_file) == 0)
  12635.         return 0;
  12636.     if (write_counted_string (auth->number_length,
  12637.                               auth->number, auth_file) == 0)
  12638.         return 0;
  12639.     if (write_counted_string (auth->name_length, auth->name, auth_file) == 0)
  12640.         return 0;
  12641.     if (write_counted_string (auth->data_length, auth->data, auth_file) == 0)
  12642.         return 0;
  12643.     return 1;
  12644. }
  12645.  
  12646. #ifdef KRB5
  12647. #ifdef K5_XAUTH
  12648. /*
  12649.  * functions to encode/decode Kerberos V5 principals
  12650.  * into something that can be reasonable spewed over
  12651.  * the wire
  12652.  *
  12653.  * Author: Tom Yu <tlyu@MIT.EDU>
  12654.  *
  12655.  * Still needs to be fixed up wrt signed/unsigned lengths, but we'll worry
  12656.  * about that later.
  12657.  */
  12658.  
  12659. /*
  12660.  * XauKrb5Encode
  12661.  *
  12662.  * this function encodes the principal passed to it in a format that can
  12663.  * easily be dealt with by stuffing it into an X packet.  Encoding is as
  12664.  * follows:
  12665.  *   length count of the realm name
  12666.  *   realm
  12667.  *   component count
  12668.  *   length of component
  12669.  *   actual principal component
  12670.  *   etc....
  12671.  *
  12672.  * Note that this function allocates a hunk of memory, which must be
  12673.  * freed to avoid nasty memory leak type things.  All counts are
  12674.  * byte-swapped if needed. (except for the total length returned)
  12675.  *
  12676.  * nevermind.... stuffing the encoded packet in net byte order just to
  12677.  * always do the right thing.  Don't have to frob with alignment that way.
  12678.  */
  12679. int
  12680. XauKrb5Encode(princ, outbuf)
  12681.     krb5_principal princ;       /* principal to encode */
  12682.     krb5_data *outbuf;          /* output buffer */
  12683. {
  12684.     CARD16 i, numparts, totlen = 0, plen, rlen;
  12685.     char *cp, *pdata;
  12686.  
  12687.     rlen = krb5_princ_realm(princ)->length;
  12688.     numparts = krb5_princ_size(princ);
  12689.     totlen = 2 + rlen + 2;      /* include room for realm length
  12690.                                    and component count */
  12691.     for (i = 0; i < numparts; i++)
  12692.         totlen += krb5_princ_component(princ, i)->length + 2;
  12693.     /* add 2 bytes each time for length */
  12694.     if ((outbuf->data = (char *)malloc(totlen)) == NULL)
  12695.         return -1;
  12696.     cp = outbuf->data;
  12697.     *cp++ = (char)((int)(0xff00 & rlen) >> 8);
  12698.     *cp++ = (char)(0x00ff & rlen);
  12699.     memcpy(cp, krb5_princ_realm(princ)->data, rlen);    /* safe */
  12700.     cp += rlen;
  12701.     *cp++ = (char)((int)(0xff00 & numparts) >> 8);
  12702.     *cp++ = (char)(0x00ff & numparts);
  12703.     for (i = 0; i < numparts; i++)
  12704.     {
  12705.         plen = krb5_princ_component(princ, i)->length;
  12706.         pdata = krb5_princ_component(princ, i)->data;
  12707.         *cp++ = (char)((int)(0xff00 & plen) >> 8);
  12708.         *cp++ = (char)(0x00ff & plen);
  12709.         memcpy(cp, pdata, plen);                        /* safe */
  12710.         cp += plen;
  12711.     }
  12712.     outbuf->length = totlen;
  12713.     return 0;
  12714. }
  12715.  
  12716. /*
  12717.  * XauKrb5Decode
  12718.  *
  12719.  * This function essentially reverses what XauKrb5Encode does.
  12720.  * return value: 0 if okay, -1 if malloc fails, -2 if inbuf format bad
  12721.  */
  12722. int
  12723. XauKrb5Decode(inbuf, princ)
  12724.     krb5_data inbuf;
  12725.     krb5_principal *princ;
  12726. {
  12727.     CARD16 i, numparts, plen, rlen;
  12728.     CARD8 *cp, *pdata;
  12729.  
  12730.     if (inbuf.length < 4)
  12731.     {
  12732.         return -2;
  12733.     }
  12734.     *princ = (krb5_principal)malloc(sizeof (krb5_principal_data));
  12735.     if (*princ == NULL)
  12736.         return -1;
  12737.     bzero(*princ, sizeof (krb5_principal_data));
  12738.     cp = (CARD8 *)inbuf.data;
  12739.     rlen = *cp++ << 8;
  12740.     rlen |= *cp++;
  12741.     if (inbuf.length < 4 + (int)rlen + 2)
  12742.     {
  12743.         krb5_free_principal(*princ);
  12744.         return -2;
  12745.     }
  12746.     krb5_princ_realm(*princ)->data = (char *)malloc(rlen);
  12747.     if (krb5_princ_realm(*princ)->data == NULL)
  12748.     {
  12749.         krb5_free_principal(*princ);
  12750.         return -1;
  12751.     }
  12752.     krb5_princ_realm(*princ)->length = rlen;
  12753.     memcpy(krb5_princ_realm(*princ)->data, cp, rlen);   /* safe */
  12754.     cp += rlen;
  12755.     numparts = *cp++ << 8;
  12756.     numparts |= *cp++;
  12757.     krb5_princ_name(*princ) =
  12758.         (krb5_data *)malloc(numparts * sizeof (krb5_data));
  12759.     if (krb5_princ_name(*princ) == NULL)
  12760.     {
  12761.         krb5_free_principal(*princ);
  12762.         return -1;
  12763.     }
  12764.     krb5_princ_size(*princ) = 0;
  12765.     for (i = 0; i < numparts; i++)
  12766.     {
  12767.         if (cp + 2 > (CARD8 *)inbuf.data + inbuf.length)
  12768.         {
  12769.             krb5_free_principal(*princ);
  12770.             return -2;
  12771.         }
  12772.         plen = *cp++ << 8;
  12773.         plen |= *cp++;
  12774.         if (cp + plen > (CARD8 *)inbuf.data + inbuf.length)
  12775.         {
  12776.             krb5_free_principal(*princ);
  12777.             return -2;
  12778.         }
  12779.         pdata = (CARD8 *)malloc(plen);
  12780.         if (pdata == NULL)
  12781.         {
  12782.             krb5_free_principal(*princ);
  12783.             return -1;
  12784.         }
  12785.         krb5_princ_component(*princ, i)->data = (char *)pdata;
  12786.         krb5_princ_component(*princ, i)->length = plen;
  12787.         memcpy(pdata, cp, plen);        /* safe */
  12788.         cp += plen;
  12789.         krb5_princ_size(*princ)++;
  12790.     }
  12791.     return 0;
  12792. }
  12793. #endif /* K5_XAUTH */
  12794. #endif /* KRB5 */
  12795. #endif /* CK_FORWARD_X */
  12796. #endif /* CK_AUTHENTICATION */
  12797.  
  12798. #ifdef CK_SECURITY
  12799. /* C K _ A U T H _ I N I T
  12800.  * Initialize the Kerberos system for a pending connection
  12801.  *   hostname - a reverse DNS lookup of the hostname when possible
  12802.  *   ipaddr   - the ip address of the host
  12803.  *   username - the name the user wants to connect under not necessarily
  12804.  *              the same as principal
  12805.  *   socket   - the socket handle (ttyfd in Kermit speak)
  12806.  *
  12807.  * Returns: 1 on success and 0 on failure
  12808.  */
  12809.  
  12810. int
  12811. #ifdef CK_ANSIC
  12812. ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
  12813. #else /* CK_ANSIC */
  12814. ck_auth_init( hostname, ipaddr, username, socket )
  12815.     char * hostname; char * ipaddr; char *username; int socket;
  12816. #endif /* CK_ANSIC */
  12817. {
  12818. #ifdef CK_AUTHENTICATION
  12819. #ifdef OS2
  12820.     if ( !ck_security_loaddll() ) {
  12821.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  12822.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  12823.         return(0);
  12824.     }
  12825. #endif /* OS2 */
  12826. #endif /* CK_AUTHENTICAITON */
  12827. #ifdef CK_ENCRYPTION
  12828.     if ( !!ck_crypt_is_installed() ) {
  12829.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  12830.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  12831.     }
  12832. #endif /* CK_ENCRYPTION */
  12833.  
  12834.     if (!hostname) hostname = "";
  12835.     if (!ipaddr) ipaddr = "";
  12836.     if (!username) username = "";
  12837.  
  12838.     debug(F110,"ck_auth_init Username",username,0);
  12839.     debug(F110,"ck_auth_init Hostname",hostname,0);
  12840.     debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
  12841.  
  12842.     ckstrncpy( szUserName, username, UIDBUFLEN );
  12843.     ckstrncpy( szHostName, hostname, UIDBUFLEN );
  12844.     ckstrncpy( szIP, ipaddr, 16 );
  12845.     szUserNameRequested[0] = '\0';
  12846.     szUserNameAuthenticated[0] = '\0';
  12847.     validUser = AUTH_REJECT;
  12848.     accept_complete = 0;
  12849.     authentication_version = AUTHTYPE_NULL;
  12850.  
  12851. #ifdef CK_AUTHENTICATION
  12852.     auth_how = 0;
  12853.     auth_crypt = 0;
  12854.     auth_fwd = 0;
  12855.     mutual_complete = 0;
  12856.     if ( sstelnet )
  12857.         str_data[3] = TELQUAL_REPLY;
  12858.     else
  12859.         str_data[3] = TELQUAL_IS;
  12860. #endif /* CK_AUTHENTICATION */
  12861.  
  12862. #ifdef CK_SRP
  12863.     srp_waitresp = 0;
  12864. #endif /* SRP */
  12865.  
  12866. #ifdef CK_KERBEROS
  12867. #ifdef KRB5
  12868.     /* free previous ret_cred  */
  12869.     if ( ret_cred ) {
  12870. #ifdef CK_ENCRYPTION
  12871. #ifdef HEIMDAL
  12872.         if ( k5_session_key == &ret_cred->session)
  12873.             k5_session_key = NULL;
  12874. #else /* HEIMDAL */
  12875.         if ( k5_session_key == &ret_cred->keyblock)
  12876.             k5_session_key = NULL;
  12877. #endif /* HEIMDAL */
  12878. #endif /* CK_ENCRYPTION */
  12879.         krb5_free_creds(k5_context, ret_cred);
  12880.         ret_cred = NULL;
  12881.     }
  12882.     if (k5_ticket) {
  12883.         krb5_free_ticket(k5_context, k5_ticket);
  12884.         k5_ticket = NULL;
  12885.     }
  12886.     /* and context */
  12887.     if ( k5_context ) {
  12888.         krb5_free_context(k5_context);
  12889.         k5_context = NULL;
  12890.     }
  12891.  
  12892.     /* create k5_context */
  12893.     krb5_init_context(&k5_context);
  12894. #ifndef MIT_CURRENT
  12895.     if (k5_context)
  12896.         krb5_init_ets(k5_context);
  12897. #endif /* MIT_CURRENT */
  12898.     memset(&k5_auth,0,sizeof(k5_auth));
  12899.     if (auth_context) {
  12900.         krb5_auth_con_free(k5_context, auth_context);
  12901.         auth_context = 0;
  12902.     }
  12903. #ifdef CK_ENCRYPTION
  12904.     if (k5_session_key) {
  12905.         krb5_free_keyblock(k5_context, k5_session_key);
  12906.         k5_session_key = 0;
  12907.     }
  12908. #endif /* ENCRYPTION */
  12909. #ifdef TLS_VERIFY
  12910.     krb5_tls_verified = 0;
  12911. #endif /* TLS_VERIFY */
  12912. #endif /* KRB5 */
  12913.  
  12914. #ifdef KRB4
  12915. #ifdef CK_ENCRYPTION
  12916.     /* Initialize buffers used for authentication */
  12917.     memset(&k4_session_key, 0, sizeof(k4_session_key));
  12918.     memset(&k4_challenge, 0, sizeof(k4_challenge));
  12919. #endif /* ENCRYPTION */
  12920. #endif /* KRB4 */
  12921.  
  12922.     kstream_destroy();
  12923. #ifdef RLOGCODE
  12924.     rlog_encrypt = 0;
  12925. #endif /* RLOGCODE */
  12926.     nstored = 0;
  12927.     store_ptr = storage;
  12928.     memset(storage,0,sizeof(storage));
  12929.  
  12930.     if (!kstream_create_from_fd(socket, NULL))
  12931.         return(0);
  12932. #endif /* CK_KERBEROS */
  12933.  
  12934.     return(1);
  12935. }
  12936.  
  12937. void
  12938. auth_finished(result) int result; {
  12939.     extern char uidbuf[];
  12940.     extern int sstelnet;
  12941.  
  12942.     validUser = result;
  12943.     switch (result) {
  12944.     case AUTH_REJECT:           /* Rejected */
  12945.         if (sstelnet)
  12946.             uidbuf[0] = '\0';
  12947.         authentication_version = AUTHTYPE_NULL;
  12948.         break;
  12949.     case AUTH_UNKNOWN:          /* We don't know who he is, but he's okay */
  12950.         if (sstelnet)
  12951.             strcpy(uidbuf,"(unknown)");
  12952.         break;
  12953.     case AUTH_OTHER:            /* We know him, but not his name */
  12954.         if (sstelnet)
  12955.             strcpy(uidbuf,"(other)");
  12956.         break;
  12957.     case AUTH_USER:             /* We know he name */
  12958.     case AUTH_VALID:            /* We know him, and he needs no password */
  12959.         if (sstelnet)
  12960.             strcpy(uidbuf,szUserNameRequested);
  12961.         break;
  12962.     }
  12963. }
  12964. #endif /* CK_SECURITY */
  12965.