home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc197.zip / ckuath.c < prev    next >
C/C++ Source or Header  |  2000-01-02  |  285KB  |  9,393 lines

  1. char *ckathv = "Authentication, 7.0.141, 19 Dec 1999";
  2. /*
  3.   C K U A T H . C  --  Authentication for C-Kermit
  4.  
  5.   Copyright (C) 1999, 2000,
  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.  * Based on a concatenation of all necessary source files distributed with the
  14.  * Kerberos 5 NT Alpha 2 Telnet package from MIT with significant changes.
  15.  * Additional copyrights included with affected code.
  16.  */
  17. /*
  18.  * Implements Kerberos 4/5, SRP, SSL, NTLM authentication and START_TLS
  19.  */
  20.  
  21. #include "ckcdeb.h"
  22.  
  23. #ifdef CK_AUTHENTICATION
  24. #include "ckcker.h"
  25. #include "ckucmd.h"                             /* For struct keytab */
  26. #include "ckcnet.h"
  27.  
  28. #ifdef CRYPT_DLL
  29. #ifndef LIBDES
  30. #define LIBDES
  31. #endif /* LIBDES */
  32. #ifdef OS2
  33. #ifdef NT
  34. #include <windows.h>
  35. #else /* NT */
  36. #define INCL_DOSMODULEMGR
  37. #include <os2.h>
  38. #endif /* NT */
  39. #endif /* OS2 */
  40. #endif /* CRYPT_DLL */
  41.  
  42. #ifdef NT
  43. #define KRB5_AUTOCONF__
  44. #define NTLM
  45. #endif /* NT */
  46.  
  47. #ifdef CK_KERBEROS
  48. #define KINIT
  49. #define KLIST
  50. #define KDESTROY
  51. #define CHECKADDRS
  52. #else /* CK_KERBEROS */
  53. #ifdef KRB4
  54. #undef KRB4
  55. #endif /* KRB4 */
  56. #ifdef KRB5
  57. #undef KRB5
  58. #endif /* KRB5 */
  59. #ifdef KRB524
  60. #undef KRB524
  61. #endif /* KRB524 */
  62. #endif /* CK_KERBEROS */
  63.  
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include <stdio.h>
  67. #include <time.h>
  68. #include <fcntl.h>
  69. #include <malloc.h>
  70. #ifdef OS2
  71. #include <io.h>
  72. #endif /* OS2 */
  73.  
  74. #ifdef KRB5
  75. #include "krb5.h"
  76. #include "com_err.h"
  77. #ifdef HAVE_PWD_H
  78. #include <pwd.h>
  79. #endif
  80. #ifdef UNIX
  81. #define krb5_free_unparsed_name(con,val) free((char FAR *)(val))
  82. #endif /* UNIX */
  83. #endif /* KRB5 */
  84.  
  85. #ifdef KRB4
  86. #define  des_cblock Block
  87. #define  des_key_schedule Schedule
  88. #ifdef NT
  89. #define _WINDOWS
  90. #include "kerberosIV/krb.h"
  91. #else /* NT */
  92. #ifdef KRB524
  93. #include "kerberosIV/krb.h"
  94. _PROTOTYP(const char * krb_get_err_text_entry, (int));
  95. #else /* KRB524 */
  96. #ifdef SOLARIS
  97. #ifndef sun
  98. /* for some reason the Makefile entries for the Solaris systems have -Usun */
  99. #define sun
  100. #endif /* sun */
  101. #endif /* SOLARIS */
  102. #include "krb.h"
  103. #define krb_get_err_text_entry krb_get_err_text
  104. #endif /* KRB524 */
  105. #endif /* NT */
  106. #else /* KRB4 */
  107. #ifdef CK_SSL
  108. #define  des_cblock Block
  109. #define  des_key_schedule Schedule
  110. #endif /* CK_SSL */
  111. #endif /* KRB4 */
  112.  
  113. #include "ckuath.h"
  114. #ifdef CK_KERBEROS
  115. #ifndef KRB5
  116. #define NOBLOCKDEF
  117. #endif /* KRB5 */
  118. #ifdef KRB524
  119. #define NOBLOCKDEF
  120. #endif /* KRB524 */
  121. #endif /* CK_KERBEROS */
  122. #include "ckuat2.h"
  123.  
  124. #ifdef CK_SSL
  125. #ifdef LIBDES
  126. #ifndef HEADER_DES_H
  127. #define HEADER_DES_H
  128. #endif /* HEADER_DES_H */
  129. #endif /* LIBDES */
  130. #include "ck_ssl.h"
  131. #endif /* SSL */
  132.  
  133. #define PWD_SZ 128
  134.  
  135. #ifndef LIBDES
  136. #ifdef UNIX
  137. #define des_set_random_generator_seed(x) des_init_random_number_generator(x)
  138. #endif /* UNIX */
  139. #endif /* LIBDES */
  140.  
  141.  
  142. /*
  143.  * Globals
  144.  */
  145. int authentication_version = AUTHTYPE_NULL;
  146. int auth_type_user[AUTHTYPLSTSZ]      = {AUTHTYPE_AUTO, AUTHTYPE_NULL};
  147. static int auth_how=0;
  148. static int auth_crypt=0;
  149. static int auth_fwd=0;
  150.  
  151. /* These are state completion variables */
  152. int accept_complete = 0;
  153. static int mutual_complete = 0;
  154.  
  155. #ifdef KRB4
  156. #ifdef OS2
  157. /* The Leash implementation of Kerberos 4 used by Kermit 95 */
  158. /* has an extended Credentials structure that includes the  */
  159. /* ip address of the ticket in readable form.               */
  160. #ifdef KRB4
  161. #ifndef ADDR_SZ
  162. #define ADDR_SZ 40      /* From Leash krb.h */
  163. #endif /* ADDR_SZ */
  164.  
  165. struct leash_credentials {
  166.     char    service[ANAME_SZ];  /* Service name */
  167.     char    instance[INST_SZ];  /* Instance */
  168.     char    realm[REALM_SZ];    /* Auth domain */
  169.     C_Block session;            /* Session key */
  170.     int     lifetime;           /* Lifetime */
  171.     int     kvno;               /* Key version number */
  172.     KTEXT_ST ticket_st;         /* The ticket itself */
  173.     long    issue_date;         /* The issue time */
  174.     char    pname[ANAME_SZ];    /* Principal's name */
  175.     char    pinst[INST_SZ];     /* Principal's instance */
  176.     char    address[ADDR_SZ];   /* IP Address in ticket */
  177. };
  178.  
  179. typedef struct leash_credentials LEASH_CREDENTIALS;
  180. #endif /* KRB4 */
  181. static LEASH_CREDENTIALS cred;
  182. #else /* OS2 */
  183. static CREDENTIALS cred;
  184. #endif /* OS2 */
  185. static KTEXT_ST k4_auth;
  186. static char     k4_name[ANAME_SZ];
  187. static AUTH_DAT k4_adat  = { 0 };
  188. static char *   k4_keyfile = "/etc/srvtab";
  189. static MSG_DAT  k4_msg_data;
  190. #ifdef CK_ENCRYPTION
  191. static Block    k4_session_key     = { 0 };
  192. static Schedule k4_sched;
  193. static Block    k4_challenge       = { 0 };
  194. #ifdef MIT_CURRENT
  195. static krb5_keyblock k4_krbkey;
  196. #endif /* MIT_CURRENT */
  197. #endif /* ENCRYPTION */
  198. #define KRB4_SERVICE_NAME    "rcmd"
  199.  
  200. _PROTOTYP(static int k4_auth_send,(VOID));
  201. _PROTOTYP(static int k4_auth_reply,(unsigned char *, int));
  202. _PROTOTYP(static int k4_auth_is,(unsigned char *, int));
  203. #endif /* KRB4 */
  204.  
  205. #ifdef KRB5
  206. static krb5_data          k5_auth;
  207. static krb5_auth_context  auth_context;
  208. static krb5_keyblock     *k5_session_key = NULL;
  209. #ifdef FORWARD
  210. _PROTOTYP(void kerberos5_forward,(VOID));
  211. #endif /* FORWARD */
  212.  
  213. #define KRB5_SERVICE_NAME    "host"
  214.  
  215. _PROTOTYP(static int k5_auth_send,(int,int,int));
  216. _PROTOTYP(static int k5_auth_reply,(int, unsigned char *, int));
  217. _PROTOTYP(static int k5_auth_is,(int,unsigned char *, int));
  218. _PROTOTYP(static int SendK5AuthSB,(int, void *, int));
  219. #endif /* KRB5 */
  220.  
  221. #ifdef CK_SRP
  222. _PROTOTYP(static int srp_reply,(int, unsigned char *, int));
  223. _PROTOTYP(static int srp_is,(int, unsigned char *, int));
  224. #endif /* SRP */
  225.  
  226. _PROTOTYP(void auth_finished, (int));
  227.  
  228. #ifdef CK_ENCRYPTION
  229. static int encrypt_flag = 1;
  230. #endif
  231. #ifdef FORWARD
  232. int forward_flag = 0;              /* forward tickets? */
  233. int forwardable_flag = 1;          /* get forwardable tickets to forward? */
  234. int forwarded_tickets = 0;         /* were tickets forwarded? */
  235. #endif
  236.  
  237. static unsigned char str_data[4096] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
  238.                       AUTHTYPE_KERBEROS_V5, };
  239. #define AUTHTMPBL 2048
  240. static char strTmp[AUTHTMPBL+1];
  241.        char szUserNameRequested[UIDBUFLEN+1];    /* for incoming connections */
  242.        char szUserNameAuthenticated[UIDBUFLEN+1];/* for incoming connections */
  243.        char szHostName[UIDBUFLEN+1];
  244. static char szLocalHostName[UIDBUFLEN+1];
  245. static char szIP[16];
  246. static char szUserName[UIDBUFLEN+1];
  247. static int  validUser = AUTH_REJECT;    /* User starts out invalid */
  248.  
  249. static struct kstream_crypt_ctl_block ctl;
  250. static kstream g_kstream=NULL;
  251.  
  252. #ifdef KRB5
  253. static krb5_context k5_context=NULL;
  254. static krb5_creds * ret_cred=NULL;
  255. static krb5_context telnet_context=NULL;
  256. static char * telnet_srvtab = NULL;
  257. static char * telnet_krb5_realm = NULL;
  258. static krb5_ticket * k5_ticket = NULL;
  259. #endif /* KRB5 */
  260.  
  261. #ifdef CK_SRP
  262. #include <t_pwd.h>
  263. #include <t_client.h>
  264. #include <t_server.h>
  265.  
  266. static struct t_server * ts = NULL;
  267. static struct t_client * tc = NULL;
  268. #ifdef PRE_SRP_1_4_4
  269. #ifndef PRE_SRP_1_4_5
  270. #define PRE_SRP_1_4_5
  271. #endif /* PRE_SRP_1_4_5 */
  272. static struct t_pw * tpw = NULL;
  273. static struct t_conf * tconf = NULL;
  274. #endif /* PRE_SRP_1_4_4 */
  275.  
  276. static int srp_waitresp = 0;    /* Flag to indicate readiness for response */
  277. static struct t_num * B;    /* Holder for B */
  278. static char srp_passwd[PWD_SZ];
  279. #endif /* CK_SRP */
  280.  
  281. #ifdef CK_KERBEROS
  282. #ifdef RLOGCODE
  283. #define OPTS_FORWARD_CREDS           0x00000002
  284. #define OPTS_FORWARDABLE_CREDS       0x00000001
  285.  
  286. #define RLOGIN_BUFSIZ 5120
  287. char des_inbuf[2*RLOGIN_BUFSIZ];       /* needs to be > largest read size */
  288. char des_outpkt[2*RLOGIN_BUFSIZ+4];    /* needs to be > largest write size */
  289. #ifdef KRB5
  290. krb5_data desinbuf,desoutbuf;
  291. krb5_encrypt_block eblock;             /* eblock for encrypt/decrypt */
  292. #endif /* KRB5 */
  293.  
  294. static char storage[2*RLOGIN_BUFSIZ];  /* storage for the decryption */
  295. static int nstored = 0;
  296. static char *store_ptr = storage;
  297. static int rlog_encrypt = 0;
  298. #endif /* RLOGCODE */
  299.  
  300. extern char * krb5_d_principal;        /* Default principal */
  301. extern char * krb5_d_instance;          /* Default instance */
  302. extern char * krb5_d_realm;        /* Default realm */
  303. extern char * krb5_d_cc;        /* Default credentials cache */
  304. extern char * krb5_d_srv;               /* Default service name */
  305. extern int    krb5_d_lifetime;          /* Default lifetime */
  306. extern int    krb5_d_forwardable;
  307. extern int    krb5_d_proxiable;
  308. extern int    krb5_d_renewable;
  309. extern int    krb5_autoget;
  310. extern int    krb5_checkaddrs;
  311. extern int    krb5_d_getk4;
  312.  
  313. extern int    krb5_errno;
  314. extern char * krb5_errmsg;
  315.  
  316. extern char * krb4_d_principal;        /* Default principal */
  317. extern char * krb4_d_realm;        /* Default realm */
  318. extern char * krb4_d_srv;               /* Default service name */
  319. extern int    krb4_d_lifetime;          /* Default lifetime */
  320. extern int    krb4_d_preauth;
  321. extern char * krb4_d_instance;
  322. extern int    krb4_autoget;
  323. extern int    krb4_checkaddrs;
  324.  
  325. extern int    krb4_errno;
  326. extern char * krb4_errmsg;
  327. #endif /* CK_KERBEROS */
  328.  
  329. extern char tn_msg[], hexbuf[];         /* from ckcnet.c */
  330. extern char pwbuf[];
  331. extern int  pwflg, pwcrypt;
  332. extern int deblog, debses, tn_deb;
  333. extern int sstelnet, inserver;
  334. #ifdef CK_LOGIN
  335. extern int ckxanon;
  336. #endif /* CK_LOGIN */
  337. extern int tn_auth_how;
  338. extern int tn_auth_enc;
  339. #ifdef CK_ENCRYPTION
  340. extern int cx_type;
  341. #endif /* CK_ENCRYPTION */
  342.  
  343.  
  344. #ifdef OS2
  345. #include "ckoath.c"
  346. #endif /* OS2 */
  347.  
  348. int
  349. ck_krb5_is_installed()
  350. {
  351. #ifdef KRB5
  352. #ifdef OS2
  353.     return(hKRB5_32 != NULL);
  354. #else /* OS2 */
  355.     return(1);
  356. #endif /* OS2 */
  357. #else /* KRB5 */
  358.     return(0);
  359. #endif /* KRB5 */
  360. }
  361.  
  362. int
  363. ck_krb4_is_installed()
  364. {
  365. #ifdef KRB4
  366. #ifdef OS2
  367.     return(hKRB4_32 != NULL);
  368. #else /* OS2 */
  369.     return(1);
  370. #endif /* OS2 */
  371. #else /* KRB4 */
  372.     return(0);
  373. #endif /* KRB4 */
  374. }
  375.  
  376. int
  377. ck_srp_is_installed()
  378. {
  379. #ifdef CK_SRP
  380. #ifdef SRPDLL
  381.     return(hSRP != NULL);
  382. #else /* SRPDLL */
  383.     return(1);
  384. #endif /* SRPDLL */
  385. #else /* SRP */
  386.     return(0);
  387. #endif /* SRP */
  388. }
  389.  
  390. int
  391. ck_crypt_is_installed()
  392. {
  393. #ifdef CK_ENCRYPTION
  394. #ifdef CRYPT_DLL
  395.     return(hCRYPT != NULL);
  396. #else /* CRYPT_DLL */
  397.     return(1);
  398. #endif /* CRYPT_DLL */
  399. #else /* ENCRYPTION */
  400.     return(0);
  401. #endif /* ENCRYPTION */
  402. }
  403.  
  404. int
  405. ck_ntlm_is_installed()
  406. {
  407. #ifdef NT
  408.     return(hSSPI != NULL);
  409. #else /* NT */
  410.     return(0);
  411. #endif /* NT */
  412. }
  413.  
  414. /* C K _ K R B _ I N I T
  415.  * Initialize the Kerberos system for a pending connection
  416.  *   hostname - a reverse DNS lookup of the hostname when possible
  417.  *   ipaddr   - the ip address of the host
  418.  *   username - the name the user wants to connect under not necessarily
  419.  *              the same as principal
  420.  *   socket   - the socket handle (ttyfd in Kermit speak)
  421.  *
  422.  * Returns: 1 on success and 0 on failure
  423.  */
  424.  
  425. int
  426. #ifdef CK_ANSIC
  427. ck_auth_init( char * hostname, char * ipaddr, char * username, int socket )
  428. #else /* CK_ANSIC */
  429. ck_auth_init( hostname, ipaddr, username, socket )
  430.     char * hostname; char * ipaddr; char *username; int socket;
  431. #endif /* CK_ANSIC */
  432. {
  433. #ifdef OS2
  434.     if ( !ck_auth_loaddll() ) {
  435.         TELOPT_ME_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  436.         TELOPT_U_MODE(TELOPT_AUTHENTICATION) = TN_NG_RF;
  437.         return(0);
  438.     }
  439. #endif /* OS2 */
  440.  
  441.     if ( !!ck_crypt_is_installed() ) {
  442.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  443.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  444.     }
  445.  
  446.     if (!hostname) hostname = "";
  447.     if (!ipaddr) ipaddr = "";
  448.     if (!username) username = "";
  449.  
  450.     ckstrncpy( szUserName, username, UIDBUFLEN );
  451.     ckstrncpy( szHostName, hostname, UIDBUFLEN );
  452.     ckstrncpy( szIP, ipaddr, 16 );
  453.     szUserNameRequested[0] = '\0';
  454.     szUserNameAuthenticated[0] = '\0';
  455.     validUser = AUTH_REJECT;
  456.  
  457.     if ( sstelnet )
  458.         str_data[3] = TELQUAL_REPLY;
  459.     else
  460.         str_data[3] = TELQUAL_IS;
  461.  
  462.     debug(F110,"ck_auth_init Username",username,0);
  463.     debug(F110,"ck_auth_init Hostname",hostname,0);
  464.     debug(F110,"ck_auth_init Ipaddr",ipaddr,0);
  465.  
  466. #ifdef KRB5
  467.     /* free previous ret_cred  */
  468.     if ( ret_cred ) {
  469.         krb5_free_creds(k5_context, ret_cred);
  470.         ret_cred = NULL;
  471.     }
  472.     /* and context */
  473.     if ( k5_context ) {
  474.         krb5_free_context(k5_context);
  475.         k5_context = NULL;
  476.     }
  477.  
  478.     /* create k5_context */
  479.     krb5_init_context(&k5_context);
  480. #ifndef MIT_CURRENT
  481.     krb5_init_ets(k5_context);
  482. #endif /* MIT_CURRENT */
  483.     memset(&k5_auth,0,sizeof(k5_auth));
  484.     if (auth_context) {
  485.         krb5_auth_con_free(k5_context, auth_context);
  486.         auth_context = 0;
  487.     }
  488. #ifdef CK_ENCRYPTION
  489.     if (k5_session_key) {
  490.         krb5_free_keyblock(k5_context, k5_session_key);
  491.         k5_session_key = 0;
  492.     }
  493. #endif /* ENCRYPTION */
  494. #endif /* KRB5 */
  495.  
  496. #ifdef KRB4
  497. #ifdef CK_ENCRYPTION
  498.     /* Initialize buffers used for authentication */
  499.     memset(&k4_session_key, 0, sizeof(k4_session_key));
  500.     memset(&k4_challenge, 0, sizeof(k4_challenge));
  501. #endif /* ENCRYPTION */
  502. #endif /* KRB4 */
  503.  
  504.     kstream_destroy();
  505.  
  506.     auth_how = 0;
  507.     auth_crypt = 0;
  508.     auth_fwd = 0;
  509.     accept_complete = 0;
  510.     mutual_complete = 0;
  511.     authentication_version = AUTHTYPE_NULL;
  512.  
  513. #ifdef CK_KERBEROS
  514. #ifdef RLOGCODE
  515.     rlog_encrypt = 0;
  516.     nstored = 0;
  517.     store_ptr = storage;
  518.     memset(storage,0,sizeof(storage));
  519. #endif /* RLOGCODE */
  520. #endif /* CK_KERBEROS */
  521. #ifdef CK_SRP
  522.     srp_waitresp = 0;
  523. #endif /* SRP */
  524.  
  525.     /* create kstream from socket */
  526.     /* a kstream is simply a structure containing the socket handle */
  527.     /* and pointers to the appropriate functions for encryption,    */
  528.     /* decryption, and the like.                                    */
  529.     ctl.encrypt = auth_encrypt;
  530.     ctl.decrypt = auth_decrypt;
  531.     ctl.init = auth_init;
  532.     ctl.destroy = auth_destroy;
  533.  
  534.     if (!kstream_create_from_fd(socket, &ctl, NULL))
  535.         return(0);
  536.  
  537.     return(1);
  538. }
  539.  
  540. int
  541. ck_tn_auth_valid()
  542. {
  543.     return(validUser);
  544. }
  545.  
  546. /* C K _ K R B _ A U T H _ I N _ P R O G R E S S
  547.  *
  548.  * Is an authentication negotiation still in progress?
  549.  *
  550.  */
  551.  
  552. int
  553. #ifdef CK_ANSIC
  554. ck_tn_auth_in_progress(void)
  555. #else
  556. ck_tn_auth_in_progress()
  557. #endif
  558. {
  559.     switch (authentication_version) {
  560.     case AUTHTYPE_AUTO:
  561.         return(1);
  562.     case AUTHTYPE_NULL:
  563.         return(0);
  564. #ifdef KRB4
  565.     case AUTHTYPE_KERBEROS_V4:
  566.         if (!accept_complete) {
  567.         debug(F100,"ck_auth_in_progress() Kerberos 4 !accept_complete",
  568.            "",0);
  569.             return(1);
  570.     }
  571.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  572.         debug(F100,"ck_auth_in_progress() Kerberos 4 !mutual_complete",
  573.            "",0);
  574.             return(1);
  575.     }
  576.         else
  577.             return(0);
  578. #endif /* KRB4 */
  579. #ifdef KRB5
  580.     case AUTHTYPE_KERBEROS_V5:
  581.         if (!accept_complete) {
  582.         debug(F100,"ck_auth_in_progress() Kerberos 5 !accept_complete",
  583.            "",0);
  584.             return(1);
  585.     }
  586.         else if ((auth_how & AUTH_HOW_MASK) && !mutual_complete) {
  587.         debug(F100,"ck_auth_in_progress() Kerberos 5 !mutual_complete",
  588.            "",0);
  589.             return(1);
  590.     }
  591.         else
  592.             return(0);
  593. #endif /* KRB5 */
  594. #ifdef CK_SRP
  595.     case AUTHTYPE_SRP:
  596.         if (!accept_complete || srp_waitresp)
  597.             return(1);
  598.         else
  599.             return(0);
  600. #endif /* CK_SRP */
  601. #ifdef NTLM
  602.     case AUTHTYPE_NTLM:
  603.         if (!accept_complete) {
  604.         debug(F100,"ck_auth_in_progress() NTLM !accept_complete",
  605.            "",0);
  606.             return(1);
  607.     }
  608.         else
  609.             return(0);
  610. #endif /* NTLM */
  611.     case AUTHTYPE_SSL:
  612.         if (!accept_complete) {
  613.         debug(F100,"ck_auth_in_progress() SSL !accept_complete",
  614.            "",0);
  615.             return(1);
  616.     }
  617.         else
  618.             return(0);
  619.     default:
  620.         return(0);
  621.     }
  622.     return(0);
  623. }
  624.  
  625.  
  626. /*  C K _ K R B _ T N _ A U T H _ R E Q U E S T
  627.  *
  628.  *  Builds a Telnet Authentication Send Negotiation providing the
  629.  *  list of supported authentication methods.  To be used only
  630.  *  when accepting incoming connections as only the server (DO) side of the
  631.  *  Telnet negotiation is allowed to send an AUTH SEND.
  632.  *
  633.  *  Returns: 0 on success and -1 on failure
  634.  */
  635.  
  636. int
  637. #ifdef CK_ANSIC
  638. ck_tn_auth_request(void)
  639. #else
  640. ck_tn_auth_request()
  641. #endif
  642. {
  643.     static unsigned char str_request[64] = { IAC, SB,
  644.                                                  TELOPT_AUTHENTICATION,
  645.                                                  TELQUAL_SEND };
  646.     int i = 4, rc = -1;
  647.  
  648. #ifdef CK_SSL
  649.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  650.     return(0);
  651.     }
  652. #endif /* CK_SSL */
  653.  
  654.     if ( deblog || tn_deb || debses )
  655.         strcpy(tn_msg,"TELNET SENT SB AUTHENTICATION SEND ");
  656.  
  657.     /* Create a list of acceptable Authentication types to send to */
  658.     /* the client and let it choose find one that we support       */
  659.  
  660.     /* For those authentication methods that support Encryption or */
  661.     /* Credentials Forwarding we must send all of the appropriate  */
  662.     /* combinations based upon the state of                        */
  663.     /* TELOPT_x_MODE(TELOPT_ENCRYPTION) and forward_flag.          */
  664.  
  665.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  666.         /* Microsoft's Telnet client won't perform authentication if */
  667.         /* NTLM is not first.                                        */
  668. #ifdef NTLM
  669.         if ( ck_ntlm_is_valid() ) {
  670.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  671.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  672.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  673.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  674.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  675.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  676.             {
  677.                 str_request[i++] = AUTHTYPE_NTLM;
  678.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  679.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  680.                 if ( deblog || tn_deb || debses )
  681.                     strcat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ");
  682.                 i++;
  683.             }
  684.         }
  685. #endif /* NTLM */
  686. #ifdef KRB5
  687.         if (1
  688. #ifdef OS2
  689.              && hKRB5_32
  690. #endif /* OS2 */
  691.              ) {
  692. #ifdef CK_ENCRYPTION
  693. #ifdef USE_INI_CRED_FWD
  694.             if ( forward_flag &&
  695.          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  696.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  697.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  698.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  699.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  700.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) )
  701.             {
  702.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  703.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  704.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  705.                 str_request[i] |= INI_CRED_FWD_ON;
  706.  
  707.                 if ( deblog || tn_deb || debses )
  708.          strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ");
  709.                 i++;
  710.             }
  711. #endif /* USE_INI_CRED_FWD */
  712.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  713.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  714.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  715.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  716.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  717.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  718.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  719.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  720.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  721.  
  722.                 if ( deblog || tn_deb || debses )
  723.          strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ");
  724.                 i++;
  725.             }
  726. #endif /* CK_ENCRYPTION */
  727.  
  728.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  729.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  730.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  731.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  732.             {
  733. #ifdef CK_ENCRYPTION
  734.                 /* Can't perform mutual authentication without encryption */
  735.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  736.                      tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  737.                     str_request[i++] = AUTHTYPE_KERBEROS_V5;
  738.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  739.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  740.  
  741.                     if ( deblog || tn_deb || debses )
  742.                         strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ");
  743.                     i++;
  744.                 }
  745. #endif /* CK_ENCRYPTION */
  746.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  747.                      tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  748.                     str_request[i++] = AUTHTYPE_KERBEROS_V5;
  749.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  750.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  751.  
  752.                     if ( deblog || tn_deb || debses )
  753.                         strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ");
  754.                     i++;
  755.                 }
  756.             }
  757.         }
  758. #endif /* KRB5 */
  759. #ifdef KRB4
  760.         if (1
  761. #ifdef OS2
  762.              && hKRB4_32
  763. #endif /* OS2 */
  764.              ) {
  765. #ifdef CK_ENCRYPTION
  766.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  767.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  768.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  769.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  770.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  771.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) )
  772.             {
  773.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  774.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  775.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  776.  
  777.                 if ( deblog || tn_deb || debses )
  778.          strcat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ");
  779.                 i++;
  780.             }
  781. #endif /* CK_ENCRYPTION */
  782.  
  783.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  784.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  785.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  786.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  787.             {
  788. #ifdef CK_ENCRYPTION
  789.                 /* Can't perform mutual authentication without encryption */
  790.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  791.                      tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  792.                     str_request[i++] = AUTHTYPE_KERBEROS_V4;
  793.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  794.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  795.  
  796.                     if ( deblog || tn_deb || debses )
  797.                         strcat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ");
  798.                     i++;
  799.                 }
  800. #endif /* CK_ENCRYPTION */
  801.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  802.                      tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  803.                     str_request[i++] = AUTHTYPE_KERBEROS_V4;
  804.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  805.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  806.  
  807.                     if ( deblog || tn_deb || debses )
  808.                         strcat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ");
  809.                     i++;
  810.                 }
  811.             }
  812.         }
  813. #endif /* KRB4 */
  814. #ifdef CK_SRP
  815.         if ( 1
  816. #ifdef SRPDLL
  817.              && hSRP
  818. #endif /* SRPDLL */
  819.              ) {
  820. #ifndef PRE_SRP_1_4_5
  821.           /* Dont' do this yet.  SRP when it uses the ENCRYPT_USING_TELOPT   */
  822.           /* flag it must perform a checksum of the auth-type-pair but there */
  823.           /* is no mechansim to do that yet.                                 */
  824. #ifdef CK_ENCRYPTION
  825.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  826.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  827.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  828.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  829.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  830.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  831.                 str_request[i++] = AUTHTYPE_SRP;
  832.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  833.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  834.  
  835.                 if ( deblog || tn_deb || debses )
  836.                     strcat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT ");
  837.                 i++;
  838.             }
  839. #endif /* CK_ENCRYPTION */
  840. #endif /* PRE_SRP_1_4_5 */
  841.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  842.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  843.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  844.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  845.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  846.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  847.             {
  848.                 str_request[i++] = AUTHTYPE_SRP;
  849.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  850.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  851.  
  852.                 if ( deblog || tn_deb || debses )
  853.                     strcat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ");
  854.                 i++;
  855.             }
  856.         }
  857. #endif /* SRP */
  858. #ifdef CK_SSL
  859.         if ( 1
  860. #ifdef SSLDLL
  861.              && ck_ssleay_is_installed()
  862. #endif /* SSLDLL */
  863.              && !tls_active_flag && !ssl_active_flag && ssl_initialized
  864.              ) {
  865.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  866.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  867.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  868.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  869.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  870.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  871.             {
  872.                 str_request[i++] = AUTHTYPE_SSL;
  873.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  874.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  875.                 if ( deblog || tn_deb || debses )
  876.                     strcat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ");
  877.                 i++;
  878.             }
  879.         }
  880. #endif /* CK_SSL */
  881.     } else {
  882.         int j;
  883.         for ( j=0;
  884.               j<AUTHTYPLSTSZ && auth_type_user[j] != AUTHTYPE_NULL;
  885.               j++) {
  886. #ifdef NTLM
  887.         if (auth_type_user[j] == AUTHTYPE_NTLM &&
  888.             ck_ntlm_is_valid()) {
  889.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  890.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  891.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  892.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  893.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  894.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  895.             {
  896.                 str_request[i++] = AUTHTYPE_NTLM;
  897.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  898.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  899.                 if ( deblog || tn_deb || debses )
  900.                     strcat(tn_msg,"NTLM CLIENT_TO_SERVER|ONE_WAY ");
  901.                 i++;
  902.             }
  903.         }
  904. #endif /* NTLM */
  905. #ifdef CK_SSL
  906.         if ( auth_type_user[j] == AUTHTYPE_SSL
  907. #ifdef SSLDLL
  908.              && ck_ssleay_is_installed()
  909. #endif /* SSLDLL */
  910.              && !tls_active_flag && !ssl_active_flag && ssl_initialized
  911.              )
  912.         {
  913.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  914.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  915.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  916.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  917.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  918.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  919.             {
  920.                 str_request[i++] = AUTHTYPE_SSL;
  921.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  922.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  923.                 if ( deblog || tn_deb || debses )
  924.                     strcat(tn_msg,"SSL CLIENT_TO_SERVER|ONE_WAY ");
  925.                 i++;
  926.             }
  927.         }
  928. #endif /* CK_SSL */
  929. #ifdef CK_SRP
  930.         if ( auth_type_user[j] == AUTHTYPE_SRP
  931. #ifdef SRPDLL
  932.              && hSRP
  933. #endif /* SRPDLL */
  934.              )
  935.         {
  936. #ifndef PRE_SRP_1_4_5
  937.           /* Dont' do this yet.  SRP when it uses the ENCRYPT_USING_TELOPT   */
  938.           /* flag it must perform a checksum of the auth-type-pair but there */
  939.           /* is no mechansim to do that yet.                                 */
  940. #ifdef CK_ENCRYPTION
  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_ONE_WAY)  &&
  945.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  946.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  947.                 str_request[i++] = AUTHTYPE_SRP;
  948.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  949.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  950.  
  951.                 if ( deblog || tn_deb || debses )
  952.                     strcat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY|ENCRYPT ");
  953.                 i++;
  954.             }
  955. #endif /* CK_ENCRYPTION */
  956. #endif /* PRE_SRP_1_4_5 */
  957.  
  958.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  959.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  960.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  961.                    tn_auth_how == TN_AUTH_HOW_ONE_WAY)  &&
  962.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  963.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  964.             {
  965.                 str_request[i++] = AUTHTYPE_SRP;
  966.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  967.                 str_request[i] |= AUTH_ENCRYPT_OFF;
  968.  
  969.                 if ( deblog || tn_deb || debses )
  970.                     strcat(tn_msg,"SRP CLIENT_TO_SERVER|ONE_WAY ");
  971.                 i++;
  972.             }
  973.         }
  974. #endif /* SRP */
  975. #ifdef KRB5
  976.         if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V5
  977. #ifdef OS2
  978.              && hKRB5_32
  979. #endif /* OS2 */
  980.              )
  981.         {
  982. #ifdef CK_ENCRYPTION
  983. #ifdef USE_INI_CRED_FWD
  984.             if ( forward_flag &&
  985.          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  986.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  987.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  988.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  989.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  990.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  991.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  992.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  993.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  994.                 str_request[i] |= INI_CRED_FWD_ON;
  995.  
  996.                 if ( deblog || tn_deb || debses )
  997.          strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ");
  998.                 i++;
  999.             }
  1000. #endif /* USE_INI_CRED_FWD */
  1001.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1002.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  1003.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1004.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1005.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1006.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  1007.                 str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1008.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1009.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1010.  
  1011.                 if ( deblog || tn_deb || debses )
  1012.          strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ");
  1013.                 i++;
  1014.             }
  1015. #endif /* CK_ENCRYPTION */
  1016.  
  1017.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1018.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  1019.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1020.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  1021.             {
  1022. #ifdef CK_ENCRYPTION
  1023.                 /* Can't perform mutual authentication without encryption */
  1024.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1025.                      tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1026.                     str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1027.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1028.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  1029.  
  1030.                     if ( deblog || tn_deb || debses )
  1031.                         strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|MUTUAL ");
  1032.                     i++;
  1033.                 }
  1034. #endif /* CK_ENCRYPTION */
  1035.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1036.                      tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1037.                     str_request[i++] = AUTHTYPE_KERBEROS_V5;
  1038.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1039.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  1040.  
  1041.                     if ( deblog || tn_deb || debses )
  1042.                         strcat(tn_msg,"KERBEROS_V5 CLIENT_TO_SERVER|ONE_WAY ");
  1043.                     i++;
  1044.                 }
  1045.             }
  1046.         }
  1047. #endif /* KRB5 */
  1048. #ifdef KRB4
  1049.         if ( auth_type_user[j] == AUTHTYPE_KERBEROS_V4
  1050. #ifdef OS2
  1051.              && hKRB4_32
  1052. #endif /* OS2 */
  1053.              )
  1054.         {
  1055. #ifdef CK_ENCRYPTION
  1056.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_RF &&
  1057.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_RF &&
  1058.                  (tn_auth_how == TN_AUTH_HOW_ANY ||
  1059.                    tn_auth_how == TN_AUTH_HOW_MUTUAL)  &&
  1060.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1061.                    tn_auth_enc == TN_AUTH_ENC_TELOPT) ) {
  1062.                 str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1063.                 str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1064.                 str_request[i] |= AUTH_ENCRYPT_USING_TELOPT;
  1065.  
  1066.                 if ( deblog || tn_deb || debses )
  1067.          strcat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL|ENCRYPT ");
  1068.                 i++;
  1069.             }
  1070. #endif /* CK_ENCRYPTION */
  1071.  
  1072.             if ((TELOPT_ME_MODE(TELOPT_ENCRYPTION) != TN_NG_MU &&
  1073.                   TELOPT_U_MODE(TELOPT_ENCRYPTION)) != TN_NG_MU &&
  1074.                  (tn_auth_enc == TN_AUTH_ENC_ANY ||
  1075.                    tn_auth_enc == TN_AUTH_ENC_NONE) )
  1076.             {
  1077. #ifdef CK_ENCRYPTION
  1078.                 /* Can't perform mutual authentication without encryption */
  1079.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1080.                      tn_auth_how == TN_AUTH_HOW_MUTUAL ) {
  1081.                     str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1082.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_MUTUAL;
  1083.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  1084.  
  1085.                     if ( deblog || tn_deb || debses )
  1086.                         strcat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|MUTUAL ");
  1087.                     i++;
  1088.                 }
  1089. #endif /* CK_ENCRYPTION */
  1090.                 if ( tn_auth_how == TN_AUTH_HOW_ANY ||
  1091.                      tn_auth_how == TN_AUTH_HOW_ONE_WAY ) {
  1092.                     str_request[i++] = AUTHTYPE_KERBEROS_V4;
  1093.                     str_request[i] = AUTH_CLIENT_TO_SERVER | AUTH_HOW_ONE_WAY;
  1094.                     str_request[i] |= AUTH_ENCRYPT_OFF;
  1095.  
  1096.                     if ( deblog || tn_deb || debses )
  1097.                         strcat(tn_msg,"KERBEROS_V4 CLIENT_TO_SERVER|ONE_WAY ");
  1098.                     i++;
  1099.                 }
  1100.             }
  1101.         }
  1102. #endif /* KRB4 */
  1103.         }
  1104.     }
  1105.  
  1106.     str_request[i++] = IAC;
  1107.     str_request[i++] = SE;
  1108.     if ( deblog || tn_deb || debses ) {
  1109.         strcat(tn_msg,"IAC SE");
  1110.     debug(F100,tn_msg,"",0);
  1111.     if (tn_deb || debses) tn_debug(tn_msg);
  1112.     }
  1113.  
  1114.     /* Send data */
  1115.     rc = ttol((CHAR *)str_request, i);
  1116.     if ( rc == i )
  1117.         return(0);
  1118.     else
  1119.         return(-1);
  1120. }
  1121.  
  1122. #ifdef CK_ENCRYPTION
  1123. VOID
  1124. ck_tn_enc_start()
  1125. {
  1126.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1127.         return;
  1128.     if (!TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop &&
  1129.      (!encrypt_is_decrypting() || !encrypt_is_encrypting())) {
  1130.     debug(F110,"ck_tn_enc_start","nothing to do",0);
  1131.         return;
  1132.     }
  1133.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1134.     if (TELOPT_ME(TELOPT_ENCRYPTION) && !encrypt_is_encrypting()) {
  1135.     debug(F110,"ck_tn_enc_start","encrypt_request_start",0);
  1136.         encrypt_request_start();
  1137.     }
  1138.     if (TELOPT_U(TELOPT_ENCRYPTION) && !encrypt_is_decrypting()) {
  1139.     debug(F110,"ck_tn_enc_start","encrypt_send_request_start",0);
  1140.         encrypt_send_request_start();
  1141.     }
  1142.     tn_wait("encrypt start");
  1143.     tn_push();
  1144. }
  1145.  
  1146. VOID
  1147. ck_tn_enc_stop()
  1148. {
  1149.     if (!TELOPT_ME(TELOPT_ENCRYPTION) && !TELOPT_U(TELOPT_ENCRYPTION))
  1150.         return;
  1151.     if (TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop ||
  1152.      !(encrypt_is_decrypting() || encrypt_is_encrypting())) {
  1153.     debug(F110,"ck_tn_enc_stop","nothing to do",0);
  1154.       return;
  1155.     }
  1156.     TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1157.     if (TELOPT_U(TELOPT_ENCRYPTION) && encrypt_is_decrypting()) {
  1158.     debug(F110,"ck_tn_enc_stop","encrypt_send_request_end",0);
  1159.         encrypt_send_request_end();
  1160.     }
  1161.     if (TELOPT_ME(TELOPT_ENCRYPTION) && encrypt_is_encrypting()) {
  1162.     debug(F110,"ck_tn_enc_stop","encrypt_send_end",0);
  1163.         encrypt_send_end();
  1164.     }
  1165.     tn_wait("encrypt stop");
  1166.     tn_push();
  1167. }
  1168. #endif /* CK_ENCRYPTION */
  1169.  
  1170. /*  C K _ K R B _ T N _ S B _ A U T H
  1171.  *  An interface between the C-Kermit Telnet Command Parser and the Authent-
  1172.  *  ication option parser implemented in the Kerberos Telnet client.
  1173.  *
  1174.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1175.  *  len  - the length of the buffer
  1176.  *
  1177.  *  Returns: 0 on success and -1 on failure
  1178.  */
  1179.  
  1180. int
  1181. #ifdef CK_ANSIC
  1182. ck_tn_sb_auth(char * sb, int len)
  1183. #else /* CK_ANSIC */
  1184. ck_tn_sb_auth(sb,len) char * sb; int len;
  1185. #endif /* CK_ANSIC */
  1186. {
  1187.     /* auth_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1188.     /* and it wants the length to exclude the IAC SE bytes                  */
  1189.     char buf[1024];
  1190.     int rc = -1;
  1191.  
  1192.     buf[0] = SB;
  1193.     memcpy( &buf[1], sb, len );
  1194.     buf[len+1] = '\0';
  1195.     rc = auth_parse(buf,len+1-2);
  1196.     debug(F111,"ck_tn_sb_auth","rc",rc);
  1197.     if (rc == AUTH_FAILURE) {
  1198.         authentication_version = AUTHTYPE_NULL;
  1199. #ifdef OS2
  1200.         ipadl25();
  1201. #endif /* OS2 */
  1202.         return(-1);
  1203.     }
  1204. #ifdef OS2
  1205.     ipadl25();
  1206. #endif /* OS2 */
  1207.     return(0);
  1208. }
  1209.  
  1210. /*  C K _ K R B _ T N _ S B _ E N C R Y P T
  1211.  *  An interface between the C-Kermit Telnet Command Parser and the Encryption
  1212.  *  option parser implemented in the Kerberos Telnet client.
  1213.  *
  1214.  *  sb   - the subnegotiation as calculated in ckcnet.c
  1215.  *  len  - the length of the buffer
  1216.  *
  1217.  *  Returns: Always returns 0 for success since encrypt_parse is void
  1218.  */
  1219.  
  1220.  
  1221. int
  1222. #ifdef CK_ANSIC
  1223. ck_tn_sb_encrypt(char * sb, int len)
  1224. #else
  1225. ck_tn_sb_encrypt(sb,len) char * sb; int len;
  1226. #endif /* CK_ANSIC */
  1227. {
  1228.     /* encrypt_parse() assumes that sb starts at pos 1 not 0 as in ckcnet.c */
  1229.     /* and it wants the length to exclude the IAC SE bytes                  */
  1230. #ifdef CK_ENCRYPTION
  1231.     char buf[1024];
  1232.     buf[0] = SB;
  1233.     memcpy( &buf[1], sb, len );
  1234.     buf[len+1] = '\0';
  1235.     if (encrypt_parse(buf,len+1-2) < 0)
  1236.     return(-1);
  1237.  
  1238.     /* This is a hack.  It does not belong here but should really be in */
  1239.     /* encrypt_parse() but in K95 the encrypt_parse() routine does not  */
  1240.     /* have access to the telopt_states array.                          */
  1241.     if ( buf[1] == ENCRYPT_REQEND )
  1242.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 1;
  1243.     else if ( buf[1] == ENCRYPT_REQSTART )
  1244.         TELOPT_SB(TELOPT_ENCRYPTION).encrypt.stop = 0;
  1245. #ifdef OS2
  1246.     ipadl25();
  1247. #endif /* OS2 */
  1248. #endif /* ENCRYPTION */
  1249.     return(0);
  1250. }
  1251.  
  1252.  
  1253. /*  C K _ K R B _ E N C R Y P T I N G
  1254.  *  Returns 1 if we are encrypting and 0 if we are not
  1255.  */
  1256.  
  1257. int
  1258. #ifdef CK_ANSIC
  1259. ck_tn_encrypting(VOID)
  1260. #else /* CK_ANSIC */
  1261. ck_tn_encrypting()
  1262. #endif /* CK_ANSIC */
  1263. {
  1264. #ifdef CK_ENCRYPTION
  1265.     if ( g_kstream == NULL )
  1266.         return(0);
  1267.     if ( g_kstream->encrypt && encrypt_is_encrypting()) {
  1268.     debug(F111,"ck_tn_encrypting","encrypting",
  1269.            g_kstream->encrypt_type);
  1270.         return(g_kstream->encrypt_type);
  1271.     }
  1272. #endif /* CK_ENCRYPTION */
  1273.     debug(F110,"ck_tn_encrypting","not encrypting",0);
  1274.     return(0);
  1275. }
  1276.  
  1277. /*  C K _ K R B _ D E C R Y P T I N G
  1278.  *  Returns 1 if we are decrypting and 0 if we are not
  1279.  */
  1280.  
  1281. int
  1282. #ifdef CK_ANSIC
  1283. ck_tn_decrypting(VOID)
  1284. #else
  1285. ck_tn_decrypting()
  1286. #endif /* CK_ANSIC */
  1287. {
  1288. #ifdef CK_ENCRYPTION
  1289.     if ( g_kstream == NULL )
  1290.         return(0);
  1291.     if ( g_kstream->decrypt && encrypt_is_decrypting()) {
  1292.     debug(F111,"ck_tn_decrypting","decrypting",
  1293.            g_kstream->decrypt_type);
  1294.         return(g_kstream->decrypt_type);
  1295.     }
  1296. #endif /* CK_ENCRYPTION */
  1297.     debug(F110,"ck_tn_decrypting","not decrypting",0);
  1298.     return(0);
  1299. }
  1300.  
  1301. /*  C K _ K R B _ A U T H E N T I C A T E D
  1302.  *  Returns the authentication type: AUTHTYPE_NULL, AUTHTYPE_KERBEROS4,
  1303.  *  or AUTHTYPE_KERBEROS5, AUTHTYPE_SRP, ... (see ckctel.h)
  1304.  */
  1305.  
  1306. int
  1307. #ifdef CK_ANSIC
  1308. ck_tn_authenticated(VOID)
  1309. #else
  1310. ck_tn_authenticated()
  1311. #endif
  1312. {
  1313.     return(authentication_version);
  1314. }
  1315.  
  1316. /*  C K _ K R B _ E N C R Y P T
  1317.  *  encrypts n characters in s if we are encrypting
  1318.  */
  1319.  
  1320. VOID
  1321. #ifdef CK_ANSIC
  1322. ck_tn_encrypt( char * s, int n )
  1323. #else
  1324. ck_tn_encrypt( s,n ) char * s; int n;
  1325. #endif
  1326. {
  1327. #ifdef CK_ENCRYPTION
  1328.     struct kstream_data_block i;
  1329.  
  1330.     if (g_kstream->encrypt && encrypt_is_encrypting()) {
  1331. #ifdef DEBUG
  1332.       hexdump("from plaintext", s, n);
  1333. #endif
  1334.         i.ptr = s;
  1335.         i.length = n;
  1336.         g_kstream->encrypt(&i, NULL);
  1337. #ifdef DEBUG
  1338.         hexdump("to cyphertext", s, n);
  1339. #endif
  1340.     }
  1341.     else debug(F101,"ck_tn_encrypt not encrypting","",n);
  1342. #endif /* ENCRYPTION */
  1343. }
  1344.  
  1345. /*  C K _ K R B _ D E C R Y P T
  1346.  *  decrypts n characters in s if we are decrypting
  1347.  */
  1348.  
  1349. VOID
  1350. #ifdef CK_ANSIC
  1351. ck_tn_decrypt( char * s, int n )
  1352. #else
  1353. ck_tn_decrypt( s,n ) char * s; int n;
  1354. #endif
  1355. {
  1356. #ifdef CK_ENCRYPTION
  1357.     struct kstream_data_block i;
  1358.  
  1359.     if (g_kstream->decrypt && encrypt_is_decrypting()) {
  1360.  
  1361. #ifdef DEBUG
  1362.         hexdump("from cyphertext", s, n);
  1363. #endif
  1364.  
  1365.         i.ptr = s;
  1366.         i.length = n;
  1367.         g_kstream->decrypt(&i, NULL);
  1368. #ifdef DEBUG
  1369.         hexdump("to plaintext", s, n);
  1370. #endif
  1371.     }
  1372.     else debug(F101,"ck_tn_decrypt not decrypting","",n);
  1373. #endif /* ENCRYPTION */
  1374. }
  1375.  
  1376. /*  S E N D K 5 A U T H S B
  1377.  *  Send a Kerberos 5 Authentication Subnegotiation to host and
  1378.  *  output appropriate Telnet Debug messages
  1379.  *
  1380.  *  type - Sub Negotiation type
  1381.  *  data - ptr to buffer containing data
  1382.  *  len  - len of buffer if not NUL terminated
  1383.  *
  1384.  *  returns number of characters sent or error value
  1385.  */
  1386.  
  1387. static int
  1388. #ifdef CK_ANSIC
  1389. SendK5AuthSB(int type, void *data, int len)
  1390. #else
  1391. SendK5AuthSB(type,data,len) int type; void *data; int len;
  1392. #endif
  1393. {
  1394.     int rc;
  1395.     unsigned char *p = str_data + 3;
  1396.     unsigned char *cd = (unsigned char *)data;
  1397.     extern int sstelnet;
  1398.  
  1399. #ifdef CK_SSL
  1400.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1401.         if (ttchk() < 0)
  1402.       return(0);
  1403.         else
  1404.       return(1);
  1405.     }
  1406. #endif /* CK_SSL */
  1407.  
  1408.     if ( type < 0 || type > 6 )         /* Check for invalid values */
  1409.         return(0);
  1410.  
  1411.     if (!cd) {
  1412.         cd = (unsigned char *)"";
  1413.         len = 0;
  1414.     }
  1415.  
  1416.     if (len == -1)                        /* Use strlen() for len */
  1417.         len = strlen((char *)cd);
  1418.  
  1419.     /* Construct Message */
  1420.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1421.     *p++ = AUTHTYPE_KERBEROS_V5;
  1422.     *p = AUTH_CLIENT_TO_SERVER;
  1423.     *p |= auth_how;
  1424. #ifdef CK_ENCRYPTION
  1425.     *p |= auth_crypt;
  1426. #endif
  1427. #ifdef USE_INI_CRED_FWD
  1428.     if (auth_fwd)
  1429.         *p |= INI_CRED_FWD_ON;
  1430. #endif /* USE_INI_CRED_FWD */
  1431.     p++;
  1432.     *p++ = type;
  1433.     while (len-- > 0) {
  1434.         if ((*p++ = *cd++) == IAC)
  1435.             *p++ = IAC;
  1436.     }
  1437.     *p++ = IAC;
  1438.     *p++ = SE;
  1439.  
  1440.     /* Handle Telnet Debugging Messages */
  1441.     if (deblog || tn_deb || debses) {
  1442.         int i;
  1443.         int deblen=p-str_data-2;
  1444.         char *s=NULL;
  1445.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1446.             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF)
  1447. #ifdef USE_INI_CRED_FWD
  1448.               | (auth_fwd?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  1449. #endif /* USE_INI_CRED_FWD */
  1450.                     ;
  1451.  
  1452.         switch (type) {
  1453.         case 0:
  1454.             s = "AUTH";
  1455.             break;
  1456.         case 1:
  1457.             s = "REJECT";
  1458.             break;
  1459.         case 2:
  1460.             s = "ACCEPT";
  1461.             break;
  1462.         case 3:
  1463.             s = "RESPONSE";
  1464.             break;
  1465.         case 4:
  1466.             s = "FORWARD";
  1467.             break;
  1468.         case 5:
  1469.             s = "FORWARD_ACCEPT";
  1470.             break;
  1471.         case 6:
  1472.             s = "FORWARD_REJECT";
  1473.             break;
  1474.         }
  1475.  
  1476.     sprintf(tn_msg,"TELNET SENT SB %s %s %s %s %s ",
  1477.                  TELOPT(TELOPT_AUTHENTICATION),
  1478.                  str_data[3] == TELQUAL_IS ? "IS" :
  1479.                  str_data[3] == TELQUAL_REPLY ? "REPLY" : "???",
  1480.                  authtype_names[authentication_version],
  1481.                  authmode_names[mode],
  1482.                  s);
  1483. #ifdef HEXDISP
  1484.         {
  1485.             int was_hex = 1;
  1486.             for ( i=7;i<deblen;i++ ) {
  1487.                 if ( str_data[i] < 32 || str_data[i] >= 127) {
  1488.                     sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",str_data[i]);
  1489.                     was_hex = 1;
  1490.                 } else {
  1491.                     sprintf(hexbuf,"%s%c",was_hex?"\"":"",str_data[i]);
  1492.                     was_hex = 0;
  1493.                 }
  1494.                 strcat(tn_msg,hexbuf);
  1495.             }
  1496.             if ( !was_hex )
  1497.                 strcat(tn_msg,"\" ");
  1498.         }
  1499. #else /* HEXDISP */
  1500.         memcpy(hexbuf,&str_data[7],deblen-7);
  1501.         hexbuf[deblen-7] = ' ';
  1502.         hexbuf[deblen-6] = '\0';
  1503.         strcat(tn_msg,hexbuf);
  1504. #endif /* HEXDISP */
  1505.         strcat(tn_msg,"IAC SE");
  1506.     debug(F100,tn_msg,"",0);
  1507.     if (tn_deb || debses) tn_debug(tn_msg);
  1508.     }
  1509.  
  1510.     /* Send data */
  1511.     rc = ttol((CHAR *)str_data, p - str_data);
  1512.     debug(F111,"SendK5AuthSB","ttol()",rc);
  1513.     return(rc);
  1514. }
  1515.  
  1516. /*  S E N D K 4 A U T H S B
  1517.  *  Send a Kerberos 4 Authentication Subnegotiation to host and
  1518.  *  output appropriate Telnet Debug messages
  1519.  *
  1520.  *  type - Sub Negotiation type
  1521.  *  data - ptr to buffer containing data
  1522.  *  len  - len of buffer if not NUL terminated
  1523.  *
  1524.  *  returns number of characters sent or error value
  1525.  */
  1526.  
  1527. static int
  1528. #ifdef CK_ANSIC
  1529. SendK4AuthSB(int type, void *data, int len)
  1530. #else
  1531. SendK4AuthSB(type,data,len) int type; void *data; int len;
  1532. #endif
  1533. {
  1534.     int rc;
  1535.     unsigned char *p = str_data + 3;
  1536.     unsigned char *cd = (unsigned char *)data;
  1537.     extern int sstelnet;
  1538.     int mode = (auth_how & AUTH_HOW_MASK) |
  1539.         (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF) ;
  1540.  
  1541.     if ( type < 0 || type > 4 )         /* Check for invalid values */
  1542.         return(0);
  1543.  
  1544. #ifdef CK_SSL
  1545.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1546.         if (ttchk() < 0)
  1547.       return(0);
  1548.         else
  1549.       return(1);
  1550.     }
  1551. #endif /* CK_SSL */
  1552.  
  1553.     if (!cd) {
  1554.         cd = (unsigned char *)"";
  1555.         len = 0;
  1556.     }
  1557.  
  1558.     if (len == -1)                        /* Use strlen() for len */
  1559.         len = strlen((char *)cd);
  1560.  
  1561.  
  1562.     /* Construct Message */
  1563.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1564.     *p++ = AUTHTYPE_KERBEROS_V4;
  1565.     *p = AUTH_CLIENT_TO_SERVER;
  1566.     *p |= mode;
  1567.     p++;
  1568.     *p++ = type;
  1569.     while (len-- > 0) {
  1570.         if ((*p++ = *cd++) == IAC)
  1571.             *p++ = IAC;
  1572.         }
  1573.     *p++ = IAC;
  1574.     *p++ = SE;
  1575.  
  1576.     /* Handle Telnet Debugging Messages */
  1577.     if (deblog || tn_deb || debses) {
  1578.         int i;
  1579.         int deblen=p-str_data-2;
  1580.         char *s=NULL;
  1581.  
  1582.         switch (type) {
  1583.         case 0:
  1584.             s = "AUTH";
  1585.             break;
  1586.         case 1:
  1587.             s = "REJECT";
  1588.             break;
  1589.         case 2:
  1590.             s = "ACCEPT";
  1591.             break;
  1592.         case 3:
  1593.             s = "CHALLENGE";
  1594.             break;
  1595.         case 4:
  1596.             s = "RESPONSE";
  1597.             break;
  1598.         }
  1599.  
  1600.     sprintf(tn_msg,"TELNET SENT SB %s %s %s %s %s ",
  1601.                  TELOPT(TELOPT_AUTHENTICATION),
  1602.                  str_data[3] == TELQUAL_IS ? "IS" :
  1603.                  (str_data[3] == TELQUAL_REPLY ? "REPLY" : "???"),
  1604.                  authtype_names[authentication_version],
  1605.                  authmode_names[mode],
  1606.                  s);
  1607. #ifdef HEXDISP
  1608.         {
  1609.             int was_hex = 1;
  1610.             for ( i=7;i<deblen;i++ ) {
  1611.                 if ( str_data[i] < 32 || str_data[i] >= 127) {
  1612.                     sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",str_data[i]);
  1613.                     was_hex = 1;
  1614.                 } else {
  1615.                     sprintf(hexbuf,"%s%c",was_hex?"\"":"",str_data[i]);
  1616.                     was_hex = 0;
  1617.                 }
  1618.                 strcat(tn_msg,hexbuf);
  1619.             }
  1620.             if ( !was_hex )
  1621.                 strcat(tn_msg,"\" ");
  1622.         }
  1623. #else /* HEXDISP */
  1624.         memcpy(hexbuf,&str_data[7],deblen-7);
  1625.         hexbuf[deblen-7] = ' ';
  1626.         hexbuf[deblen-6] = '\0';
  1627.         strcat(tn_msg,hexbuf);
  1628. #endif /* HEXDISP */
  1629.         strcat(tn_msg,"IAC SE");
  1630.     debug(F100,tn_msg,"",0);
  1631.     if (tn_deb || debses) tn_debug(tn_msg);
  1632.     }
  1633.  
  1634.     /* Send data */
  1635.     rc = ttol((CHAR *)str_data, p - str_data);
  1636.     debug(F111,"SendK4AuthSB","ttol()",rc);
  1637.     return(rc);
  1638. }
  1639.  
  1640. /*  S E N D S R P A U T H S B
  1641.  *  Send a SRP Authentication Subnegotiation to host and
  1642.  *  output appropriate Telnet Debug messages
  1643.  *
  1644.  *  type - Sub Negotiation type
  1645.  *  data - ptr to buffer containing data
  1646.  *  len  - len of buffer if not NUL terminated
  1647.  *
  1648.  *  returns number of characters sent or error value
  1649.  */
  1650.  
  1651. static int
  1652. #ifdef CK_ANSIC
  1653. SendSRPAuthSB(int type, void *data, int len)
  1654. #else
  1655. SendSRPAuthSB(type,data,len) int type; void *data; int len;
  1656. #endif
  1657. {
  1658.     int rc;
  1659.     unsigned char *p = str_data + 3;
  1660.     unsigned char *cd = (unsigned char *)data;
  1661.     extern int sstelnet;
  1662.  
  1663.     /* Check for invalid values */
  1664.     if ( type != SRP_EXP && type != SRP_RESPONSE &&
  1665.          type != SRP_REJECT && type != SRP_ACCEPT &&
  1666.          type != SRP_CHALLENGE && type != SRP_PARAMS &&
  1667.          type != SRP_AUTH)
  1668.         return(0);
  1669.  
  1670.     if (len == -1)                        /* Use strlen() for len */
  1671.         len = strlen((char *)cd);
  1672.  
  1673.     /* Construct Message */
  1674.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1675.     *p++ = AUTHTYPE_SRP;
  1676.     *p = AUTH_CLIENT_TO_SERVER;
  1677.     *p |= auth_how;
  1678. #ifdef CK_ENCRYPTION
  1679.     *p |= auth_crypt;
  1680. #endif
  1681.     p++;
  1682.     *p++ = type;
  1683.     while (len-- > 0) {
  1684.         if ((*p++ = *cd++) == IAC)
  1685.             *p++ = IAC;
  1686.         }
  1687.     *p++ = IAC;
  1688.     *p++ = SE;
  1689.  
  1690.     /* Handle Telnet Debugging Messages */
  1691.     if (deblog || tn_deb || debses) {
  1692.         int i;
  1693.         int deblen=p-str_data-2;
  1694.         char *s=NULL;
  1695.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1696.             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
  1697.  
  1698.         switch (type) {
  1699.         case 0:
  1700.             s = "AUTH";
  1701.             break;
  1702.         case 1:
  1703.             s = "REJECT";
  1704.             break;
  1705.         case 2:
  1706.             s = "ACCEPT";
  1707.             break;
  1708.         case 3:
  1709.             s = "CHALLENGE";
  1710.             break;
  1711.         case 4:
  1712.             s = "RESPONSE";
  1713.             break;
  1714.         case 5:
  1715.             s = "FORWARD";
  1716.             break;
  1717.         case 6:
  1718.             s = "FORWARD_ACCEPT";
  1719.             break;
  1720.         case 7:
  1721.             s = "FORWARD_REJECT";
  1722.             break;
  1723.         case 8:
  1724.             s = "EXP";
  1725.             break;
  1726.         case 9:
  1727.             s = "PARAMS";
  1728.             break;
  1729.         }
  1730.  
  1731.     sprintf(tn_msg,"TELNET SENT SB %s %s %s %s %s ",
  1732.                  TELOPT(TELOPT_AUTHENTICATION),
  1733.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  1734.                  str_data[3] == TELQUAL_IS ? "IS" : "???",
  1735.                  authtype_names[authentication_version],
  1736.                  authmode_names[mode],
  1737.                  s);
  1738. #ifdef HEXDISP
  1739.         {
  1740.             int was_hex = 1;
  1741.             for ( i=7;i<deblen;i++ ) {
  1742.                 if ( str_data[i] < 32 || str_data[i] >= 127) {
  1743.                     sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",str_data[i]);
  1744.                     was_hex = 1;
  1745.                 } else {
  1746.                     sprintf(hexbuf,"%s%c",was_hex?"\"":"",str_data[i]);
  1747.                     was_hex = 0;
  1748.                 }
  1749.                 strcat(tn_msg,hexbuf);
  1750.             }
  1751.             if ( !was_hex )
  1752.                 strcat(tn_msg,"\" ");
  1753.         }
  1754. #else /* HEXDISP */
  1755.         memcpy(hexbuf,&str_data[7],deblen-7);
  1756.         hexbuf[deblen-7] = ' ';
  1757.         hexbuf[deblen-6] = '\0';
  1758.         strcat(tn_msg,hexbuf);
  1759. #endif /* HEXDISP */
  1760.         strcat(tn_msg,"IAC SE");
  1761.     debug(F100,tn_msg,"",0);
  1762.     if (tn_deb || debses) tn_debug(tn_msg);
  1763.     }
  1764.  
  1765.     /* Send data */
  1766.     rc = ttol((CHAR *)str_data, p - str_data);
  1767.     return(rc);
  1768. }
  1769.  
  1770. #ifdef CK_ENCRYPTION
  1771. /*
  1772.  * Function: Enable or disable the encryption process.
  1773.  *
  1774.  * Parameters:
  1775.  *    enable - TRUE to enable, FALSE to disable.
  1776.  */
  1777. static VOID
  1778. #ifdef CK_ANSIC
  1779. auth_encrypt_enable(BOOL enable)
  1780. #else
  1781. auth_encrypt_enable(enable) BOOL enable;
  1782. #endif
  1783. {
  1784.   encrypt_flag = enable;
  1785. }
  1786. #endif
  1787.  
  1788. /*
  1789.  * Function: Abort the authentication process
  1790.  *
  1791.  * Parameters:
  1792.  */
  1793. static VOID
  1794. #ifdef CK_ANSIC
  1795. auth_abort(char *errmsg, long r)
  1796. #else
  1797. auth_abort(errmsg,r) char *errmsg; long r;
  1798. #endif
  1799. {
  1800.     char buf[9];
  1801.     extern int sstelnet;
  1802.  
  1803. #ifdef CK_SSL
  1804.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1805.     return;
  1806.     }
  1807. #endif /* CK_SSL */
  1808.     debug(F111,"auth_abort",errmsg,r);
  1809.  
  1810.     /* Construct Telnet Debugging messages */
  1811.     if (deblog || tn_deb || debses) {
  1812.     sprintf(tn_msg,"TELNET SENT SB %s IS %s %s IAC SE",
  1813.                  TELOPT(TELOPT_AUTHENTICATION),
  1814.                  authtype_names[AUTHTYPE_NULL],
  1815.                  authtype_names[AUTHTYPE_NULL]);
  1816.     debug(F100,tn_msg,"",0);
  1817.     if (tn_deb || debses) tn_debug(tn_msg);
  1818.     }
  1819.  
  1820.     /* Construct the Abort message to send to the host   */
  1821.     /* Basicly we change the authentication type to NULL */
  1822.     sprintf(buf, "%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  1823.              sstelnet ? TELQUAL_REPLY : TELQUAL_IS, AUTHTYPE_NULL,
  1824.              AUTHTYPE_NULL, IAC, SE);
  1825.     ttol((CHAR *)buf, 8);
  1826.  
  1827.     /* If there is an error message, and error number construct */
  1828.     /* an explanation to display to the user                    */
  1829.     if (errmsg != NULL) {
  1830.         ckstrncpy(strTmp, errmsg, AUTHTMPBL);
  1831.     } else
  1832.         strTmp[0] = '\0';
  1833.  
  1834.  
  1835.     if (r != AUTH_SUCCESS) {
  1836.         strcat(strTmp, "\r\n");
  1837. #ifdef KRB4
  1838.         if ( authentication_version == AUTHTYPE_KERBEROS_V4 ) {
  1839.             strcat(strTmp, (char *)krb_get_err_text_entry(r));
  1840.             debug(F111,"auth_abort",(char *)krb_get_err_text_entry(r),r);
  1841.         }
  1842. #endif
  1843. #ifdef KRB5
  1844.         if ( authentication_version == AUTHTYPE_KERBEROS_V5 ) {
  1845.             strcat(strTmp, error_message(r));
  1846.             debug(F111,"auth_abort",error_message(r),r);
  1847.         }
  1848. #endif
  1849.     }
  1850.     printf("Authentication failed: %s\r\n",strTmp);
  1851. #ifdef CKSYSLOG
  1852.     if (ckxsyslog >= SYSLG_LI && ckxlogging) {
  1853.         cksyslog(SYSLG_LI, 0, "Telnet authentication failure",
  1854.                   (char *) szUserNameRequested,
  1855.                   strTmp);
  1856.     }
  1857. #endif /* CKSYSLOG */
  1858.     authentication_version = AUTHTYPE_NULL;
  1859. }
  1860.  
  1861.  
  1862. /*
  1863.  * Function: Copy data to buffer, doubling IAC character if present.
  1864.  *
  1865.  */
  1866. static int
  1867. #ifdef CK_ANSIC
  1868. copy_for_net(unsigned char *to, unsigned char *from, int c)
  1869. #else
  1870. copy_for_net(to,from,c) unsigned char *to; unsigned char *from; int c;
  1871. #endif
  1872. {
  1873.     int n;
  1874.  
  1875.     n = c;
  1876.     debug(F111,"copy_for_net","before",n);
  1877.     while (c-- > 0) {
  1878.         if ((*to++ = *from++) == IAC) {
  1879.             n++;
  1880.             *to++ = IAC;
  1881.         }
  1882.     }
  1883.     debug(F111,"copy_for_net","after",n);
  1884.     return n;
  1885. }
  1886.  
  1887. #ifdef CK_SSL
  1888. /*  S E N D S S L A U T H S B
  1889.  *  Send a SSL Authentication Subnegotiation to host and
  1890.  *  output appropriate Telnet Debug messages
  1891.  *
  1892.  *  type - Sub Negotiation type
  1893.  *  data - ptr to buffer containing data
  1894.  *  len  - len of buffer if not NUL terminated
  1895.  *
  1896.  *  returns number of characters sent or error value
  1897.  */
  1898.  
  1899. int
  1900. #ifdef CK_ANSIC
  1901. SendSSLAuthSB(int type, void *data, int len)
  1902. #else
  1903. SendSSLAuthSB(type,data,len) int type; void *data; int len;
  1904. #endif
  1905. {
  1906.     int rc;
  1907.     unsigned char *p = str_data + 3;
  1908.     unsigned char *cd = (unsigned char *)data;
  1909.     extern int sstelnet;
  1910.  
  1911.     /* Check for invalid values */
  1912.     if ( type != SSL_START && type != SSL_ACCEPT &&
  1913.          type != SSL_REJECT)
  1914.         return(0);
  1915.  
  1916.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows) {
  1917.         if (ttchk() < 0)
  1918.       return(0);
  1919.         else
  1920.       return(1);
  1921.     }
  1922.  
  1923.     if (len == -1)                        /* Use strlen() for len */
  1924.         len = strlen((char *)cd);
  1925.  
  1926.     /* Construct Message */
  1927.     *p++ = sstelnet ? TELQUAL_REPLY : TELQUAL_IS;
  1928.     *p++ = AUTHTYPE_SSL;
  1929.     *p = AUTH_CLIENT_TO_SERVER;
  1930.     *p |= auth_how;
  1931. #ifdef CK_ENCRYPTION
  1932.     *p |= auth_crypt;
  1933. #endif
  1934.     p++;
  1935.     *p++ = type;
  1936.     while (len-- > 0) {
  1937.         if ((*p++ = *cd++) == IAC)
  1938.             *p++ = IAC;
  1939.         }
  1940.     *p++ = IAC;
  1941.     *p++ = SE;
  1942.  
  1943.     /* Handle Telnet Debugging Messages */
  1944.     if (deblog || tn_deb || debses) {
  1945.         int i;
  1946.         int deblen=p-str_data-2;
  1947.         char *s=NULL;
  1948.         int mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  1949.             (auth_crypt?AUTH_ENCRYPT_USING_TELOPT:AUTH_ENCRYPT_OFF);
  1950.  
  1951.         switch (type) {
  1952.         case SSL_START:
  1953.             s = "START";
  1954.             break;
  1955.         case SSL_ACCEPT:
  1956.             s = "ACCEPT";
  1957.             break;
  1958.         case SSL_REJECT:
  1959.             s = "REJECT";
  1960.             break;
  1961.         }
  1962.  
  1963.     sprintf(tn_msg,"TELNET SENT SB %s %s %s %s %s ",
  1964.                  TELOPT(TELOPT_AUTHENTICATION),
  1965.                  str_data[3] == TELQUAL_REPLY ? "REPLY" :
  1966.                  str_data[3] == TELQUAL_IS ? "IS" : "???",
  1967.                  authtype_names[authentication_version],
  1968.                  authmode_names[mode],
  1969.                  s);
  1970. #ifdef HEXDISP
  1971.         {
  1972.             int was_hex = 1;
  1973.             for ( i=7;i<deblen;i++ ) {
  1974.                 if ( str_data[i] < 32 || str_data[i] >= 127) {
  1975.                     sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",str_data[i]);
  1976.                     was_hex = 1;
  1977.                 } else {
  1978.                     sprintf(hexbuf,"%s%c",was_hex?"\"":"",str_data[i]);
  1979.                     was_hex = 0;
  1980.                 }
  1981.                 strcat(tn_msg,hexbuf);
  1982.             }
  1983.             if ( !was_hex )
  1984.                 strcat(tn_msg,"\" ");
  1985.         }
  1986. #else /* HEXDISP */
  1987.         memcpy(hexbuf,&str_data[7],deblen-7);
  1988.         hexbuf[deblen-7] = ' ';
  1989.         hexbuf[deblen-6] = '\0';
  1990.         strcat(tn_msg,hexbuf);
  1991. #endif /* HEXDISP */
  1992.         strcat(tn_msg,"IAC SE");
  1993.     debug(F100,tn_msg,"",0);
  1994.     if (tn_deb || debses) tn_debug(tn_msg);
  1995.     }
  1996.  
  1997.     /* Send data */
  1998.     rc = ttol((CHAR *)str_data, p - str_data);
  1999.     return(rc);
  2000. }
  2001. #endif  /* CK_SSL */
  2002.  
  2003. int
  2004. tn_how_ok(int how)
  2005. {
  2006.     switch ( tn_auth_how ) {
  2007.     case TN_AUTH_HOW_ANY:
  2008.         return(1);
  2009.     case TN_AUTH_HOW_ONE_WAY:
  2010.         return((how & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY);
  2011.     case TN_AUTH_HOW_MUTUAL:
  2012.         return((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL);
  2013.     default:
  2014.         return(0);
  2015.     }
  2016. }
  2017.  
  2018. int
  2019. tn_enc_ok(int enc)
  2020. {
  2021.     switch ( tn_auth_enc ) {
  2022.     case TN_AUTH_ENC_ANY:
  2023.         return(1);
  2024.     case TN_AUTH_ENC_NONE:
  2025.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_OFF);
  2026.     case TN_AUTH_ENC_TELOPT:
  2027.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT);
  2028.     case TN_AUTH_ENC_EXCH:
  2029.         return((enc & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_AFTER_EXCHANGE);
  2030.     default:
  2031.         return(0);
  2032.     }
  2033. }
  2034.  
  2035. static int
  2036. atok(int at) {
  2037.     int i;
  2038.     if ( auth_type_user[0] == AUTHTYPE_AUTO )
  2039.         return(1);
  2040.     if ( auth_type_user[0] == AUTHTYPE_NULL )
  2041.         return(0);
  2042.  
  2043.     for ( i=0;
  2044.           i<AUTHTYPLSTSZ && auth_type_user[i] != AUTHTYPE_NULL;
  2045.           i++ ) {
  2046.         if ( auth_type_user[i] == at )
  2047.             return(1);
  2048.     }
  2049.  
  2050.     return(0);
  2051. }
  2052.  
  2053.  
  2054. /*
  2055.  * Function: Parse authentication send command
  2056.  *
  2057.  * Parameters:
  2058.  *  parsedat - the sub-command data.
  2059.  *
  2060.  *    end_sub - index of the character in the 'parsedat' array which
  2061.  *        is the last byte in a sub-negotiation
  2062.  *
  2063.  * Returns: Kerberos error code.
  2064.  */
  2065.  
  2066.  
  2067. static int
  2068. #ifdef CK_ANSIC
  2069. auth_send(unsigned char *parsedat, int end_sub)
  2070. #else
  2071. auth_send(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  2072. #endif
  2073. {
  2074.     unsigned char buf[1024];
  2075.     unsigned char *pname;
  2076.     int plen;
  2077.     int r;
  2078.     int i;
  2079.     int mode;
  2080. #ifdef MIT_CURRENT
  2081. #ifdef CK_ENCRYPTION
  2082.     krb5_data data;
  2083.     krb5_enc_data encdata;
  2084.     krb5_error_code code;
  2085.     krb5_keyblock random_key;
  2086. #endif /* ENCRYPTION */
  2087. #endif /* MIT_CURRENT */
  2088. #ifdef KRB5
  2089.     int krb5_msg = 0;
  2090. #endif /* KRB5 */
  2091. #ifdef KRB4
  2092.     int krb4_msg = 0;
  2093.  #endif /* KRB4 */
  2094.  
  2095. #ifdef CK_SSL
  2096.     if (TELOPT_SB(TELOPT_START_TLS).start_tls.me_follows)
  2097.     return(AUTH_SUCCESS);
  2098. #endif /* CK_SSL */
  2099.  
  2100.     auth_how = -1;              /* We have not found an auth method  */
  2101.     auth_crypt = 0;             /* We are not using encryption (yet) */
  2102.  
  2103.  
  2104.     /* Search the list of acceptable Authentication types sent from */
  2105.     /* the host and find one that we support                        */
  2106.  
  2107.     /* For Kerberos authentications, try to determine if we have a  */
  2108.     /* valid TGT, if not skip over the authentication type because  */
  2109.     /* we wouldn't be able to successfully login anyway.  Perhaps   */
  2110.     /* there is another supported authentication which we could use */
  2111.  
  2112. #ifdef NO_FTP_AUTH
  2113.     /* If the userid is "ftp" or "anonymous" refuse to perform AUTH */
  2114.     /* for Kerberos or SRP.                                         */
  2115. #endif /* NO_FTP_AUTH */
  2116.  
  2117.     if ( auth_type_user[0] == AUTHTYPE_AUTO ) {
  2118.     for (i = 2; i+1 <= end_sub; i += 2) {
  2119. #ifdef NTLM
  2120.         if (parsedat[i] == AUTHTYPE_NTLM &&
  2121.              ck_ntlm_is_valid() &&
  2122.              ntlm_auth_send() == 0) {
  2123.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2124.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2125. #ifdef CK_ENCRYPTION
  2126.                 /* NTLM does not support Telnet Encryption */
  2127.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2128.                     continue;
  2129.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2130. #endif /* CK_ENCRYPTION */
  2131.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2132.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2133.                 authentication_version = AUTHTYPE_NTLM;
  2134.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2135.                 break;
  2136.             }
  2137.         }
  2138. #endif /* NTLM */
  2139. #ifdef CK_SSL
  2140.         if ( parsedat[i] == AUTHTYPE_SSL && ssl_initialized &&
  2141. #ifdef SSLDLL
  2142.              ck_ssleay_is_installed() &&
  2143. #endif /* SSLDLL */
  2144.              !tls_active_flag && !ssl_active_flag && ssl_load_certs()
  2145.              ) {
  2146.  
  2147.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2148.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2149. #ifdef CK_ENCRYPTION
  2150.                 /* SSL does not support Telnet Encryption */
  2151.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2152.                     continue;
  2153.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2154. #endif /* CK_ENCRYPTION */
  2155.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2156.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2157.                 authentication_version = AUTHTYPE_SSL;
  2158.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2159.                 break;
  2160.             }
  2161.         }
  2162. #endif /* SSL */
  2163. #ifdef CK_SRP
  2164.         if ( parsedat[i] == AUTHTYPE_SRP
  2165. #ifdef SRPDLL
  2166.              && hSRP
  2167. #endif /* SRPDLL */
  2168. #ifdef NO_FTP_AUTH
  2169.              && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2170. #endif /* NO_FTP_AUTH */
  2171.              ) {
  2172.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2173.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2174. #ifdef CK_ENCRYPTION
  2175.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2176. #ifndef PRE_SRP_1_4_5
  2177.                      /* Do not support ENCRYPT_USING_TELOPT yet. */
  2178.                      &&
  2179.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2180.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)
  2181. #endif /* PRE_SRP_1_4_5 */
  2182.                      )
  2183.                     continue;
  2184.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2185.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2186.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2187.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2188.                 }
  2189. #endif /* CK_ENCRYPTION */
  2190.                 authentication_version = AUTHTYPE_SRP;
  2191.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2192.                 break;
  2193.             }
  2194.         }
  2195. #endif /* SRP */
  2196. #ifdef KRB5
  2197.         if (parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2198. #ifdef OS2
  2199.              hKRB5_32 &&
  2200. #endif /* OS2 */
  2201. #ifdef NO_FTP_AUTH
  2202.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2203. #endif /* NO_FTP_AUTH */
  2204.              ck_krb5_is_installed() && !krb5_msg) {
  2205.  
  2206.             /* Without encryption we can't perform mutual authentication */
  2207.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2208.                  !ck_crypt_is_installed())
  2209.                 continue;
  2210.  
  2211.             /* Skip over entries that request credential forwarding */
  2212.             /* if we are not forwarding.                            */
  2213.             if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2214.                 (forward_flag &&
  2215.                   ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2216.                 continue;
  2217.  
  2218.             if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2219.                                 parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2220.                                 parsedat[i+1] & INI_CRED_FWD_MASK) )
  2221.             {
  2222.                 /* If we are auto-getting TGTs, try */
  2223.                 if ( !ck_krb5_is_tgt_valid() ) {
  2224.                 printf("Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2225.                 }
  2226.                 krb5_msg = 1;
  2227.             }
  2228.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2229.                       AUTH_CLIENT_TO_SERVER &&
  2230.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2231. #ifdef CK_ENCRYPTION
  2232.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2233.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2234.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2235.                     continue;
  2236.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2237.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2238.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2239.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2240.                 }
  2241. #endif /* CK_ENCRYPTION */
  2242.                 auth_fwd = parsedat[i+1] & INI_CRED_FWD_MASK;
  2243.                 authentication_version = AUTHTYPE_KERBEROS_V5;
  2244.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2245.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2246.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2247.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2248.                 }
  2249.                 break;
  2250.             }
  2251.         }
  2252. #endif /* KRB5 */
  2253. #ifdef KRB4
  2254.         if (parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2255. #ifdef OS2
  2256.              hKRB4_32 &&
  2257. #endif /* OS2 */
  2258. #ifdef NO_FTP_AUTH
  2259.              strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2260. #endif /* NO_FTP_AUTH */
  2261.              ck_krb4_is_installed() && !krb4_msg) {
  2262.             int rc = 0;
  2263.  
  2264.             /* Without encryption we can't perform mutual authentication */
  2265.             if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2266.                  !ck_crypt_is_installed() )
  2267.                 continue;
  2268.  
  2269.             if ( !k4_auth_send() )
  2270.             {
  2271.                 /* If we are auto-getting TGTs, try */
  2272.                 if ( !ck_krb4_is_tgt_valid() ) {
  2273.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2274.                 }
  2275.                 krb4_msg = 1;
  2276.             }
  2277.             else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2278.                       AUTH_CLIENT_TO_SERVER &&
  2279.                       tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2280. #ifdef CK_ENCRYPTION
  2281.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2282.                      (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2283.                        TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2284.                     continue;
  2285.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2286.                 if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2287.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2288.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2289.         }
  2290. #endif /* CK_ENCRYPTION */
  2291.                 authentication_version = AUTHTYPE_KERBEROS_V4;
  2292.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2293.                 if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2294.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2295.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2296.                 }
  2297.                 break;
  2298.             }
  2299.         }
  2300. #endif /* KRB4 */
  2301.     }
  2302.     } else {
  2303.         for (i = 2; i+1 <= end_sub; i += 2) {
  2304. #ifdef CK_SSL
  2305.             if ( atok(AUTHTYPE_SSL) && parsedat[i] == AUTHTYPE_SSL &&
  2306. #ifdef SSLDLL
  2307.                  ck_ssleay_is_installed() &&
  2308. #endif /* SSLDLL */
  2309.                  !tls_active_flag && !ssl_active_flag && ssl_initialized &&
  2310.                  ssl_load_certs()
  2311.                  )
  2312.             {
  2313.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2314.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2315. #ifdef CK_ENCRYPTION
  2316.                     /* SSL does not support Telnet Encryption */
  2317.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2318.                         continue;
  2319.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2320. #endif /* CK_ENCRYPTION */
  2321.                     TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2322.                     TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2323.                     authentication_version = AUTHTYPE_SSL;
  2324.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2325.                     break;
  2326.                 }
  2327.             }
  2328. #endif /* SSL */
  2329. #ifdef CK_SRP
  2330.             if ( atok(AUTHTYPE_SRP) &&
  2331.                  parsedat[i] == AUTHTYPE_SRP
  2332. #ifdef SRPDLL
  2333.                  && hSRP
  2334. #endif /* SRPDLL */
  2335. #ifdef NO_FTP_AUTH
  2336.                  && strcmp("ftp",szUserName) && strcmp("anonymous",szUserName)
  2337. #endif /* NO_FTP_AUTH */
  2338.                  ) {
  2339.                 if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2340.                      tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2341. #ifdef CK_ENCRYPTION
  2342.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK)
  2343. #ifndef PRE_SRP_1_4_5
  2344.                          /* Do not support ENCRYPT_USING_TELOPT yet. */
  2345.                          &&
  2346.                          (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2347.                            TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF)
  2348. #endif /* PRE_SRP_1_4_5 */
  2349.                          )
  2350.                         continue;
  2351.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2352.                     if ( auth_crypt == AUTH_ENCRYPT_USING_TELOPT ) {
  2353.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2354.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2355.                     }
  2356. #endif /* CK_ENCRYPTION */
  2357.                     authentication_version = AUTHTYPE_SRP;
  2358.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2359.                     break;
  2360.                 }
  2361.             }
  2362. #endif /* SRP */
  2363. #ifdef KRB5
  2364.             if ( atok(AUTHTYPE_KERBEROS_V5) &&
  2365.                  parsedat[i] == AUTHTYPE_KERBEROS_V5 &&
  2366. #ifdef OS2
  2367.                  hKRB5_32 &&
  2368. #endif /* OS2 */
  2369. #ifdef NO_FTP_AUTH
  2370.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2371. #endif /* NO_FTP_AUTH */
  2372.                  ck_krb5_is_installed() && !krb5_msg) {
  2373.  
  2374.                 /* Without encryption we can't perform mutual authentication */
  2375.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2376.                      !ck_crypt_is_installed())
  2377.                     continue;
  2378.  
  2379.                 /* Skip over entries that request credential forwarding */
  2380.                 /* if we are not forwarding.                            */
  2381.                 if ((!forward_flag && (parsedat[i+1] & INI_CRED_FWD_MASK)) ||
  2382.                      (forward_flag &&
  2383.                        ((parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY)))
  2384.                     continue;
  2385.  
  2386.                 if ( !k5_auth_send(parsedat[i+1] & AUTH_HOW_MASK,
  2387.                                     parsedat[i+1] & AUTH_ENCRYPT_MASK,
  2388.                                     parsedat[i+1] & INI_CRED_FWD_MASK) )
  2389.                 {
  2390.                     /* If we are auto-getting TGTs, try */
  2391.                     if ( !ck_krb5_is_tgt_valid() ) {
  2392.                         printf(
  2393.                "Kerberos 5: Ticket Getting Ticket not valid.\r\n");
  2394.                     }
  2395.                     krb5_msg = 1;
  2396.                 }
  2397.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2398.                           AUTH_CLIENT_TO_SERVER &&
  2399.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2400.                 {
  2401. #ifdef CK_ENCRYPTION
  2402.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2403.             (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2404.              TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2405.               continue;
  2406.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2407.                     if (auth_crypt) {
  2408.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2409.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2410.                     }
  2411. #endif /* CK_ENCRYPTION */
  2412.                     authentication_version = AUTHTYPE_KERBEROS_V5;
  2413.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2414.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2415.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2416.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2417.                     }
  2418.                     break;
  2419.                 }
  2420.             }
  2421. #endif /* KRB5 */
  2422. #ifdef KRB4
  2423.             if ( atok(AUTHTYPE_KERBEROS_V4) &&
  2424.                  parsedat[i] == AUTHTYPE_KERBEROS_V4 &&
  2425. #ifdef OS2
  2426.                  hKRB4_32 &&
  2427. #endif /* OS2 */
  2428. #ifdef NO_FTP_AUTH
  2429.                  strcmp("ftp",szUserName) && strcmp("anonymous",szUserName) &&
  2430. #endif /* NO_FTP_AUTH */
  2431.                  ck_krb4_is_installed() && !krb4_msg) {
  2432.                 int rc = 0;
  2433.  
  2434.                 /* Without encryption we can't perform mutual authentication */
  2435.                 if ( (parsedat[i+1] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL &&
  2436.                      !ck_crypt_is_installed())
  2437.                     continue;
  2438.  
  2439.                 if ( !k4_auth_send() )
  2440.                 {
  2441.                     /* If we are auto-getting TGTs, try */
  2442.                     if ( !ck_krb4_is_tgt_valid() ) {
  2443.                     printf("Kerberos 4: Ticket Getting Ticket not valid.\r\n");
  2444.                     }
  2445.                     krb4_msg = 1;
  2446.                 }
  2447.                 else if ((parsedat[i+1] & AUTH_WHO_MASK) ==
  2448.                           AUTH_CLIENT_TO_SERVER &&
  2449.                           tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1]))
  2450.                 {
  2451. #ifdef CK_ENCRYPTION
  2452.                     if ((parsedat[i+1] & AUTH_ENCRYPT_MASK) &&
  2453.             (TELOPT_ME_MODE(TELOPT_ENCRYPTION) == TN_NG_RF ||
  2454.              TELOPT_U_MODE(TELOPT_ENCRYPTION) == TN_NG_RF))
  2455.               continue;
  2456.                     auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2457.                     if (auth_crypt) {
  2458.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2459.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_MU;
  2460.                     }
  2461. #endif /* CK_ENCRYPTION */
  2462.                     authentication_version = AUTHTYPE_KERBEROS_V4;
  2463.                     auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2464.                     if ( auth_how == AUTH_HOW_ONE_WAY ) {
  2465.                         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2466.                         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2467.                     }
  2468.                     break;
  2469.                 }
  2470.             }
  2471. #endif /* KRB4 */
  2472. #ifdef NTLM
  2473.         if ( atok(AUTHTYPE_NTLM) &&
  2474.              parsedat[i] == AUTHTYPE_NTLM &&
  2475.              ck_ntlm_is_valid() &&
  2476.              ntlm_auth_send() == 0) {
  2477.             if ((parsedat[i+1] & AUTH_WHO_MASK) == AUTH_CLIENT_TO_SERVER &&
  2478.                  tn_how_ok(parsedat[i+1]) && tn_enc_ok(parsedat[i+1])) {
  2479. #ifdef CK_ENCRYPTION
  2480.                 /* NTLM does not support Telnet Encryption */
  2481.                 if ((parsedat[i+1] & AUTH_ENCRYPT_MASK))
  2482.                     continue;
  2483.                 auth_crypt = parsedat[i+1] & AUTH_ENCRYPT_MASK;
  2484. #endif /* CK_ENCRYPTION */
  2485.                 TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2486.                 TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2487.                 authentication_version = AUTHTYPE_NTLM;
  2488.                 auth_how = parsedat[i+1] & AUTH_HOW_MASK;
  2489.                 break;
  2490.             }
  2491.         }
  2492. #endif /* NTLM */
  2493.         }
  2494.     }
  2495.  
  2496.     if (auth_how == -1) {               /* Did we find one? */
  2497.         switch ( auth_type_user[0] ) {  /* If not, abort the negotiation */
  2498.         case AUTHTYPE_NULL:
  2499.             auth_abort("User refused to accept any authentication method",0);
  2500.             break;
  2501.         case AUTHTYPE_AUTO:
  2502.             auth_abort("No authentication method available", 0);
  2503.             break;
  2504.         default: {
  2505.             char msg[80];
  2506.             sprintf(msg,"%s could not be negotiated",
  2507.                      authtype_names[auth_type_user[0]]);
  2508.             auth_abort(msg, 0);
  2509.         }
  2510.         }
  2511.         auth_finished(AUTH_REJECT);
  2512.         return AUTH_FAILURE;
  2513.     }
  2514.  
  2515.     printf("Authenticating with %s\r\n",
  2516.             authtype_names[authentication_version]);
  2517.  
  2518.     /* Send Telnet Auth Name message (if necessary) */
  2519.     switch ( authentication_version ) {
  2520.     case AUTHTYPE_SRP:
  2521.     case AUTHTYPE_KERBEROS_V4:
  2522.     case AUTHTYPE_KERBEROS_V5:
  2523.         /* if we do not have a name to login with get one now. */
  2524.         while ( szUserName[0] == '\0' ) {
  2525.             extern char * tn_pr_uid;
  2526.             readtext(tn_pr_uid && tn_pr_uid[0] ? tn_pr_uid : "Host Userid: ",
  2527.                       szUserName,63);
  2528.         }
  2529.         plen = strlen(szUserName);
  2530.         pname = (unsigned char *) szUserName;
  2531.  
  2532.         /* Construct Telnet Debugging Message */
  2533.         if (deblog || tn_deb || debses) {
  2534.             sprintf(tn_msg,"TELNET SENT SB %s NAME %s IAC SE",
  2535.                      TELOPT(TELOPT_AUTHENTICATION),
  2536.                      pname);
  2537.             debug(F100,tn_msg,"",0);
  2538.             if (tn_deb || debses) tn_debug(tn_msg);
  2539.         }
  2540.  
  2541.         /* Construct and send Authentication Name subnegotiation */
  2542.         sprintf(buf, "%c%c%c%c", IAC, SB, TELOPT_AUTHENTICATION,
  2543.                  TELQUAL_NAME);
  2544.         memcpy(&buf[4], pname, plen);
  2545.         sprintf(&buf[plen + 4], "%c%c", IAC, SE);
  2546.         ttol((CHAR *)buf, plen+6);
  2547.     }
  2548.  
  2549.     /* Construct Authentication Mode subnegotiation message (if necessary) */
  2550.     switch ( authentication_version ) {
  2551.     case AUTHTYPE_SRP:
  2552.     case AUTHTYPE_KERBEROS_V4:
  2553.     case AUTHTYPE_KERBEROS_V5:
  2554.     case AUTHTYPE_NTLM:
  2555.         mode = AUTH_CLIENT_TO_SERVER | (auth_how & AUTH_HOW_MASK) |
  2556.             (auth_crypt ? AUTH_ENCRYPT_USING_TELOPT : AUTH_ENCRYPT_OFF)
  2557. #ifdef USE_INI_CRED_FWD
  2558.                 | (((authentication_version == AUTHTYPE_KERBEROS_V5) &&
  2559.                   auth_fwd)?INI_CRED_FWD_ON:INI_CRED_FWD_OFF)
  2560. #endif /* USE_INI_CRED_FWD */
  2561.                     ;
  2562.         sprintf(buf, "%c%c%c%c%c%c%c",
  2563.                  IAC, SB, TELOPT_AUTHENTICATION,
  2564.                  TELQUAL_IS,
  2565.                  authentication_version,
  2566.                  mode,
  2567.                  KRB_AUTH);
  2568.         break;
  2569.     }
  2570.  
  2571.     /* Send initial authentication data */
  2572.     switch ( authentication_version ) {
  2573. #ifdef CK_SSL
  2574.     case AUTHTYPE_SSL:
  2575.         SendSSLAuthSB(SSL_START,NULL,0);
  2576.         break;
  2577. #endif /* SSL */
  2578. #ifdef CK_SRP
  2579.     case AUTHTYPE_SRP:
  2580.         sprintf(&buf[7], "%c%c", IAC, SE);
  2581.         if (deblog || tn_deb || debses) {
  2582.             int i;
  2583.             sprintf(tn_msg,"TELNET SENT SB %s IS %s %s AUTH ",
  2584.                      TELOPT(TELOPT_AUTHENTICATION),
  2585.                      authtype_names[authentication_version],
  2586.                      authmode_names[mode]);
  2587.             strcat(tn_msg,"IAC SE");
  2588.             debug(F100,tn_msg,"",0);
  2589.             if (tn_deb || debses) tn_debug(tn_msg);
  2590.         }
  2591.         ttol((CHAR *)buf, 9);
  2592.         break;
  2593. #endif /* SRP */
  2594. #ifdef NTLM
  2595.     case AUTHTYPE_NTLM: {
  2596.         int length = 0;
  2597.  
  2598.         length = copy_for_net(&buf[7],(char *)&NTLMSecBuf[0],2*sizeof(ULONG));
  2599.         length += copy_for_net(&buf[7+length], NTLMSecBuf[0].pvBuffer,
  2600.                                   NTLMSecBuf[0].cbBuffer);
  2601.         sprintf(&buf[7+length], "%c%c", IAC, SE);
  2602.  
  2603.         if (deblog || tn_deb || debses) {
  2604.             int i;
  2605.             sprintf(tn_msg,"TELNET SENT SB %s IS %s %s NTLM_AUTH ",
  2606.                      TELOPT(TELOPT_AUTHENTICATION),
  2607.                      authtype_names[authentication_version],
  2608.                      authmode_names[mode]);
  2609. #ifdef HEXDISP
  2610.             {
  2611.                 int was_hex = 1;
  2612.                 for ( i=0;i<length;i++ ) {
  2613.                     if ( buf[i+7] < 32 || buf[i+7] >= 127) {
  2614.                         sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",buf[i+7]);
  2615.                         was_hex = 1;
  2616.                     } else {
  2617.                         sprintf(hexbuf,"%s%c",was_hex?"\"":"",buf[i+7]);
  2618.                         was_hex = 0;
  2619.                     }
  2620.                     strcat(tn_msg,hexbuf);
  2621.                 }
  2622.                 if ( !was_hex )
  2623.                     strcat(tn_msg,"\" ");
  2624.             }
  2625. #else /* HEXDISP */
  2626.             memcpy(hexbuf,&buf[7],length);
  2627.             hexbuf[length] = ' ';
  2628.             hexbuf[length+1] = '\0';
  2629.             strcat(tn_msg,hexbuf);
  2630. #endif /* HEXDISP */
  2631.             strcat(tn_msg,"IAC SE");
  2632.             debug(F100,tn_msg,"",0);
  2633.             if (tn_deb || debses) tn_debug(tn_msg);
  2634.         }
  2635.         ttol((CHAR *)buf, length+9);
  2636.         break;
  2637.     }
  2638. #endif /* NTLM */
  2639. #ifdef KRB4
  2640.     case AUTHTYPE_KERBEROS_V4:
  2641.         k4_auth.length = copy_for_net(&buf[7], k4_auth.dat, k4_auth.length);
  2642.         sprintf(&buf[k4_auth.length+7], "%c%c", IAC, SE);
  2643.  
  2644.         if (deblog || tn_deb || debses) {
  2645.             int i;
  2646.             sprintf(tn_msg,"TELNET SENT SB %s IS %s %s AUTH ",
  2647.                      TELOPT(TELOPT_AUTHENTICATION),
  2648.                      authtype_names[authentication_version],
  2649.                      authmode_names[mode]);
  2650. #ifdef HEXDISP
  2651.             {
  2652.                 int was_hex = 1;
  2653.                 for ( i=0;i<k4_auth.length;i++ ) {
  2654.                     if ( buf[i+7] < 32 || buf[i+7] >= 127) {
  2655.                         sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",buf[i+7]);
  2656.                         was_hex = 1;
  2657.                     } else {
  2658.                         sprintf(hexbuf,"%s%c",was_hex?"\"":"",buf[i+7]);
  2659.                         was_hex = 0;
  2660.                     }
  2661.                     strcat(tn_msg,hexbuf);
  2662.                 }
  2663.                 if ( !was_hex )
  2664.                     strcat(tn_msg,"\" ");
  2665.             }
  2666. #else /* HEXDISP */
  2667.             memcpy(hexbuf,&buf[7],k4_auth.length);
  2668.             hexbuf[k4_auth.length] = ' ';
  2669.             hexbuf[k4_auth.length+1] = '\0';
  2670.             strcat(tn_msg,hexbuf);
  2671. #endif /* HEXDISP */
  2672.             strcat(tn_msg,"IAC SE");
  2673.             debug(F100,tn_msg,"",0);
  2674.             if (tn_deb || debses) tn_debug(tn_msg);
  2675.         }
  2676.         ttol((CHAR *)buf, k4_auth.length+9);
  2677.  
  2678. #ifndef REMOVE_FOR_EXPORT
  2679. #ifdef CK_ENCRYPTION
  2680.         /*
  2681.          * If we are doing mutual authentication, get set up to send
  2682.          * the challenge, and verify it when the response comes back.
  2683.          */
  2684.         if ((auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  2685.             register int i;
  2686.             int rc = 0;
  2687.  
  2688. #ifdef MIT_CURRENT
  2689.             data.data = cred.session;
  2690.             data.length = 8; /* sizeof(cred.session) */;
  2691.  
  2692.             if (code = krb5_c_random_seed(k5_context, &data)) {
  2693.                 com_err("libtelnet", code,
  2694.                          "while seeding random number generator");
  2695.                 return(0);
  2696.             }
  2697.  
  2698.             if (code = krb5_c_make_random_key(k5_context,
  2699.                                                ENCTYPE_DES_CBC_RAW,
  2700.                                                &random_key)) {
  2701.                 com_err("libtelnet", code,
  2702.                          "while creating random session key");
  2703.                 return(0);
  2704.             }
  2705.  
  2706.             /* the krb4 code uses ecb mode, but on a single block
  2707.             with a zero ivec, ecb and cbc are the same */
  2708.             k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  2709.             k4_krbkey.length = 8;
  2710.             k4_krbkey.contents = cred.session;
  2711.  
  2712.             encdata.ciphertext.data = random_key.contents;
  2713.             encdata.ciphertext.length = random_key.length;
  2714.             encdata.enctype = ENCTYPE_UNKNOWN;
  2715.  
  2716.             data.data = k4_session_key;
  2717.             data.length = 8;
  2718.  
  2719.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  2720.                                    &encdata, &data);
  2721.  
  2722.             krb5_free_keyblock_contents(k5_context, &random_key);
  2723.  
  2724.             if (code) {
  2725.                 com_err("libtelnet", code, "while encrypting random key");
  2726.                 return(0);
  2727.             }
  2728.  
  2729.             encdata.ciphertext.data = k4_session_key;
  2730.             encdata.ciphertext.length = 8;
  2731.             encdata.enctype = ENCTYPE_UNKNOWN;
  2732.  
  2733.             data.data = k4_challenge;
  2734.             data.length = 8;
  2735.  
  2736.             code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  2737.                                    &encdata, &data);
  2738. #else /* MIT_CURRENT */
  2739.             memset(k4_sched,0,sizeof(Schedule));
  2740.             hexdump("auth_send",cred.session,8);
  2741.             rc = des_key_sched(cred.session, k4_sched);
  2742.             if ( rc == -1 ) {
  2743.                 printf("?Invalid DES key specified in credentials\r\n");
  2744.                 debug(F110,"auth_send",
  2745.               "invalid DES Key specified in credentials",0);
  2746.             } else if ( rc == -2 ) {
  2747.                 printf("?Weak DES key specified in credentials\r\n");
  2748.                 debug(F110,"auth_send",
  2749.               "weak DES Key specified in credentials",0);
  2750.             } else if ( rc != 0 ) {
  2751.                 printf("?DES Key Schedule not set by credentials\r\n");
  2752.                 debug(F110,"auth_send",
  2753.               "DES Key Schedule not set by credentials",0);
  2754.             }
  2755.             hexdump("auth_send schedule",k4_sched,8*16);
  2756.  
  2757.             des_set_random_generator_seed(cred.session);
  2758.  
  2759.             do {
  2760.                 des_new_random_key(k4_session_key);
  2761.                 des_fixup_key_parity(k4_session_key);
  2762.             } while ( ck_des_is_weak_key(k4_session_key) );
  2763.  
  2764.             hexdump("auth_send des_new_random_key(k4_session_key)",
  2765.                      k4_session_key,8);
  2766.  
  2767.             /* Decrypt the session key so that we can send it to the */
  2768.             /* host as a challenge                                   */
  2769. #ifdef NT
  2770.             des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 0);
  2771. #else /* NT */
  2772.             des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 0);
  2773. #endif /* NT */
  2774.         hexdump(
  2775.         "auth_send des_ecb_encrypt(k4_session_key,k4_session_key,0)",
  2776.                 k4_session_key,8
  2777.             );
  2778.             /* Prepare the result of the challenge */
  2779.             /* Decrypt the session_key, add 1, and then encrypt it */
  2780.             /* The result stored in k4_challenge should match the  */
  2781.             /* KRB4_RESPONSE value from the host.                  */
  2782. #ifdef NT
  2783.             des_ecb_encrypt(k4_session_key, k4_challenge, k4_sched, 0);
  2784. #else /* NT */
  2785.             des_ecb_encrypt(&k4_session_key, &k4_challenge, k4_sched, 0);
  2786. #endif /* NT */
  2787.  
  2788.             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,0)",
  2789.                      k4_challenge,8);
  2790. #endif /* MIT_CURRENT */
  2791.             /*
  2792.             * Increment the challenge by 1, and encrypt it for
  2793.             * later comparison.
  2794.             */
  2795.             for (i = 7; i >= 0; --i) {
  2796.                 register int x;
  2797.                 x = (unsigned int)k4_challenge[i] + 1;
  2798.                 k4_challenge[i] = x;    /* ignore overflow */
  2799.                 if (x < 256)            /* if no overflow, all done */
  2800.                     break;
  2801.             }
  2802.             hexdump("auth_send k4_challenge+1",k4_challenge,8);
  2803. #ifdef MIT_CURRENT
  2804.             data.data = k4_challenge;
  2805.             data.length = 8;
  2806.  
  2807.             encdata.ciphertext.data = k4_challenge;
  2808.             encdata.ciphertext.length = 8;
  2809.             encdata.enctype = ENCTYPE_UNKNOWN;
  2810.  
  2811.             if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0, &data,
  2812.                                        &encdata)) {
  2813.                 com_err("libtelnet", code, "while encrypting random key");
  2814.                 return(0);
  2815.             }
  2816. #else /* MIT_CURRENT */
  2817. #ifdef NT
  2818.             des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  2819. #else /* NT */
  2820.             des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  2821. #endif /* NT */
  2822.             hexdump("auth_send des_ecb_encrypt(k4_session_key,k4_challenge,1)",
  2823.                      k4_challenge,8);
  2824. #endif /* MIT_CURRENT */
  2825.         }
  2826. #endif  /* ENCRYPTION */
  2827. #endif /* REMOVE_FOR_EXPORT */
  2828.         break;
  2829. #endif /* KRB4 */
  2830. #ifdef KRB5
  2831.     case AUTHTYPE_KERBEROS_V5:
  2832.         k5_auth.length = copy_for_net(&buf[7], k5_auth.data, k5_auth.length);
  2833.         sprintf(&buf[k5_auth.length+7], "%c%c", IAC, SE);
  2834.  
  2835.         if (deblog || tn_deb || debses) {
  2836.             int i;
  2837.             sprintf(tn_msg,"TELNET SENT SB %s IS %s %s AUTH ",
  2838.                      TELOPT(TELOPT_AUTHENTICATION),
  2839.                      authtype_names[authentication_version],
  2840.                      authmode_names[mode]);
  2841. #ifdef HEXDISP
  2842.             {
  2843.                 int was_hex = 1;
  2844.                 for ( i=0;i<k5_auth.length;i++ ) {
  2845.                     if ( buf[i+7] < 32 || buf[i+7] >= 127) {
  2846.                         sprintf(hexbuf,"%s%02X ",was_hex?"":"\" ",buf[i+7]);
  2847.                         was_hex = 1;
  2848.                     } else {
  2849.                         sprintf(hexbuf,"%s%c",was_hex?"\"":"",buf[i+7]);
  2850.                         was_hex = 0;
  2851.                     }
  2852.                     strcat(tn_msg,hexbuf);
  2853.                 }
  2854.                 if ( !was_hex )
  2855.                     strcat(tn_msg,"\" ");
  2856.             }
  2857. #else /* HEXDISP */
  2858.             memcpy(hexbuf,&buf[7],k5_auth.length);
  2859.             hexbuf[k5_auth.length] = ' ';
  2860.             hexbuf[k5_auth.length+1] = '\0';
  2861.             strcat(tn_msg,hexbuf);
  2862. #endif /* HEXDISP */
  2863.             strcat(tn_msg,"IAC SE");
  2864.             debug(F100,tn_msg,"",0);
  2865.             if (tn_deb || debses) tn_debug(tn_msg);
  2866.         }
  2867.         ttol((CHAR *)buf, k5_auth.length+9);
  2868.         break;
  2869. #endif /* KRB5 */
  2870.     }
  2871.     return AUTH_SUCCESS;
  2872. }
  2873.  
  2874. /*
  2875.  * Function: Parse authentication REPLY command
  2876.  *
  2877.  * Parameters:
  2878.  *  parsedat - the sub-command data.
  2879.  *
  2880.  *    end_sub - index of the character in the 'parsedat' array which
  2881.  *        is the last byte in a sub-negotiation
  2882.  *
  2883.  * Returns: Kerberos error code.
  2884.  */
  2885. static int
  2886. #ifdef CK_ANSIC
  2887. auth_reply(unsigned char *parsedat, int end_sub)
  2888. #else
  2889. auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  2890. #endif
  2891. {
  2892.     int n = AUTH_FAILURE;
  2893.  
  2894.     if ( parsedat[2] != authentication_version ) {
  2895.         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
  2896.                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
  2897.                 AUTHTYPE_NAME(authentication_version),authentication_version);
  2898.         auth_finished(AUTH_REJECT);
  2899.         return(AUTH_FAILURE);
  2900.     }
  2901.     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
  2902.         printf("Authentication mode mismatch (%s != %s)\r\n",
  2903.                 AUTHMODE_NAME(parsedat[3]),
  2904.                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
  2905.         auth_finished(AUTH_REJECT);
  2906.         return(AUTH_FAILURE);
  2907.     }
  2908.  
  2909. #ifdef KRB4
  2910.     if (authentication_version == AUTHTYPE_KERBEROS_V4)
  2911.         n = k4_auth_reply(parsedat, end_sub);
  2912. #endif
  2913. #ifdef KRB5
  2914.     if (authentication_version == AUTHTYPE_KERBEROS_V5)
  2915.         n = k5_auth_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  2916. #endif
  2917. #ifdef CK_SRP
  2918.     if (authentication_version == AUTHTYPE_SRP)
  2919.         n = srp_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  2920. #endif /* SRP */
  2921. #ifdef CK_SSL
  2922.     if (authentication_version == AUTHTYPE_SSL)
  2923.         n = ssl_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  2924. #endif /* SSL */
  2925. #ifdef NTLM
  2926.     if (authentication_version == AUTHTYPE_NTLM)
  2927.         n = ntlm_reply(auth_how|auth_crypt|auth_fwd, parsedat, end_sub);
  2928. #endif /* NTLM */
  2929.     return n;
  2930. }
  2931.  
  2932.  
  2933. /*
  2934.  * Function: Parse authentication IS command
  2935.  *
  2936.  * Parameters:
  2937.  *  parsedat - the sub-command data.
  2938.  *
  2939.  *    end_sub - index of the character in the 'parsedat' array which
  2940.  *        is the last byte in a sub-negotiation
  2941.  *
  2942.  * Returns: Kerberos error code.
  2943.  */
  2944. static int
  2945. #ifdef CK_ANSIC
  2946. auth_is(unsigned char *parsedat, int end_sub)
  2947. #else
  2948. auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  2949. #endif
  2950. {
  2951.     int n = AUTH_FAILURE;
  2952.     if ( authentication_version == AUTHTYPE_AUTO ) {
  2953.         authentication_version = parsedat[2];
  2954.         auth_how = (parsedat[3] & AUTH_HOW_MASK);
  2955.         auth_crypt = (parsedat[3] & AUTH_ENCRYPT_MASK);
  2956.         auth_fwd = (parsedat[3] & INI_CRED_FWD_MASK);
  2957.         debug(F111,"auth_is","authentication_version",authentication_version);
  2958.         debug(F111,"auth_is","auth_how",auth_how);
  2959.         debug(F111,"auth_is","auth_crypt",auth_crypt);
  2960.         debug(F111,"auth_is","auth_fwd",auth_fwd);
  2961.     }
  2962.  
  2963.     if ( parsedat[2] != authentication_version ) {
  2964.         printf("Authentication version mismatch (%s [%d] != %s [%d])\r\n",
  2965.                 AUTHTYPE_NAME(parsedat[2]),parsedat[2],
  2966.                 AUTHTYPE_NAME(authentication_version),authentication_version);
  2967.         auth_finished(AUTH_REJECT);
  2968.         return(AUTH_FAILURE);
  2969.     }
  2970.     if ( parsedat[3] != (auth_how|auth_crypt|auth_fwd) ) {
  2971.         printf("Authentication mode mismatch (%s != %s)\r\n",
  2972.                 AUTHMODE_NAME(parsedat[3]),
  2973.                 AUTHMODE_NAME(auth_how|auth_crypt|auth_fwd));
  2974.         auth_finished(AUTH_REJECT);
  2975.         return(AUTH_FAILURE);
  2976.     }
  2977.  
  2978. #ifdef KRB4
  2979.     if (authentication_version == AUTHTYPE_KERBEROS_V4)
  2980.         n = k4_auth_is(parsedat, end_sub);
  2981. #endif
  2982. #ifdef KRB5
  2983.     if (authentication_version == AUTHTYPE_KERBEROS_V5)
  2984.         n = k5_auth_is(parsedat[3],parsedat, end_sub);
  2985. #endif
  2986. #ifdef CK_SRP
  2987.     if (authentication_version == AUTHTYPE_SRP)
  2988.         n = srp_is(parsedat[3], parsedat, end_sub);
  2989. #endif /* SRP */
  2990. #ifdef CK_SSL
  2991.     if (authentication_version == AUTHTYPE_SSL) {
  2992.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2993.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  2994.         n = ssl_is(parsedat, end_sub);
  2995.     }
  2996. #endif /* SSL */
  2997. #ifdef NTLM
  2998.     if (authentication_version == AUTHTYPE_NTLM) {
  2999.         TELOPT_ME_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3000.         TELOPT_U_MODE(TELOPT_ENCRYPTION) = TN_NG_RF;
  3001.         n = ntlm_is(parsedat, end_sub);
  3002.     }
  3003. #endif /* NTLM */
  3004.     debug(F111,"auth_is","n",n);
  3005.     return n;
  3006. }
  3007.  
  3008. /*
  3009.  * Function: Parse authentication NAME command
  3010.  *
  3011.  * Parameters:
  3012.  *  parsedat - the sub-command data.
  3013.  *
  3014.  *    end_sub - index of the character in the 'parsedat' array which
  3015.  *        is the last byte in a sub-negotiation
  3016.  *
  3017.  * Returns: Kerberos error code.
  3018.  */
  3019. static int
  3020. #ifdef CK_ANSIC
  3021. auth_name(unsigned char *parsedat, int end_sub)
  3022. #else
  3023. auth_name(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3024. #endif
  3025. {
  3026.     int len = (end_sub-2) > 63 ? 63 : (end_sub-2);
  3027.     if ( len > 0 ) {
  3028.         memcpy(szUserNameRequested,&parsedat[2],len);
  3029.         szUserNameRequested[len] = '\0';
  3030.     } else
  3031.       szUserNameRequested[0] = '\0';
  3032.     debug(F111,"auth_name szUserNameRequested",szUserNameRequested,len);
  3033.     return(AUTH_SUCCESS);
  3034. }
  3035.  
  3036. /*
  3037.  * Function: Parse the athorization sub-options and reply.
  3038.  *
  3039.  * Parameters:
  3040.  *    parsedat - sub-option string to parse.
  3041.  *
  3042.  *    end_sub - last charcter position in parsedat.
  3043.  */
  3044. int
  3045. auth_parse(unsigned char *parsedat, int end_sub)
  3046. {
  3047.     int rc = AUTH_FAILURE;
  3048.     switch (parsedat[1]) {
  3049.     case TELQUAL_SEND:
  3050.         rc = auth_send(parsedat, end_sub);
  3051.         break;
  3052.     case TELQUAL_REPLY:
  3053.         rc= auth_reply(parsedat, end_sub);
  3054.         break;
  3055.     case TELQUAL_IS:
  3056.         rc = auth_is(parsedat, end_sub);
  3057.         break;
  3058.     case TELQUAL_NAME:
  3059.         rc = auth_name(parsedat, end_sub);
  3060.         break;
  3061.     }
  3062.     debug(F111,"auth_parse","rc",rc);
  3063.     return(rc);
  3064. }
  3065.  
  3066.  
  3067. /*
  3068.  * Function: Initialization routine called kstream encryption system.
  3069.  *
  3070.  * Parameters:
  3071.  *  data - user data.
  3072.  */
  3073. int
  3074. #ifdef CK_ANSIC
  3075. auth_init(kstream ks)
  3076. #else
  3077. auth_init(ks) kstream_ptr ks;
  3078. #endif
  3079. {
  3080. #ifdef FORWARD
  3081.     forwarded_tickets = 0;  /* were tickets forwarded? */
  3082. #endif /* FORWARD */
  3083. #ifdef CK_ENCRYPTION
  3084.     encrypt_init(ks,cx_type);
  3085. #endif
  3086.     return 0;
  3087. }
  3088.  
  3089.  
  3090. /*
  3091.  * Function: Destroy routine called kstream encryption system.
  3092.  *
  3093.  * Parameters:
  3094.  *  data - user data.
  3095.  */
  3096. VOID
  3097. #ifdef CK_ANSIC
  3098. auth_destroy(void)
  3099. #else
  3100. auth_destroy()
  3101. #endif
  3102. {
  3103. }
  3104.  
  3105.  
  3106. /*
  3107.  * Function: Callback to encrypt a block of characters
  3108.  *
  3109.  * Parameters:
  3110.  *  out - return as pointer to converted buffer.
  3111.  *
  3112.  *  in - the buffer to convert
  3113.  *
  3114.  * Returns: number of characters converted.
  3115.  */
  3116. int
  3117. #ifdef CK_ANSIC
  3118. auth_encrypt(struct kstream_data_block *out,
  3119.          struct kstream_data_block *in)
  3120. #else
  3121. auth_encrypt(out,in)
  3122.     struct kstream_data_block *out; struct kstream_data_block *in;
  3123. #endif
  3124. {
  3125.     out->ptr = in->ptr;
  3126.  
  3127.     out->length = in->length;
  3128.  
  3129.     return(out->length);
  3130. }
  3131.  
  3132.  
  3133. /*
  3134.  * Function: Callback to decrypt a block of characters
  3135.  *
  3136.  * Parameters:
  3137.  *  out - return as pointer to converted buffer.
  3138.  *
  3139.  *  in - the buffer to convert
  3140.  *
  3141.  * Returns: number of characters converted.
  3142.  */
  3143. int
  3144. #ifdef CK_ANSIC
  3145. auth_decrypt(struct kstream_data_block *out,
  3146.          struct kstream_data_block *in)
  3147. #else
  3148. auth_decrypt(out,in)
  3149.     struct kstream_data_block *out; struct kstream_data_block *in;
  3150. #endif
  3151. {
  3152.     out->ptr = in->ptr;
  3153.  
  3154.     out->length = in->length;
  3155.  
  3156.     return(out->length);
  3157. }
  3158.  
  3159. void
  3160. auth_finished(result) int result; {
  3161.     extern char uidbuf[];
  3162.     extern int sstelnet;
  3163.  
  3164.     validUser = result;
  3165.     switch (result) {
  3166.     case AUTH_REJECT:           /* Rejected */
  3167.         if (sstelnet)
  3168.             uidbuf[0] = '\0';
  3169.         authentication_version = AUTHTYPE_NULL;
  3170.         break;
  3171.     case AUTH_UNKNOWN:          /* We don't know who he is, but he's okay */
  3172.         if (sstelnet)
  3173.             strcpy(uidbuf,"(unknown)");
  3174.         break;
  3175.     case AUTH_OTHER:            /* We know him, but not his name */
  3176.         if (sstelnet)
  3177.             strcpy(uidbuf,"(other)");
  3178.         break;
  3179.     case AUTH_USER:             /* We know he name */
  3180.     case AUTH_VALID:            /* We know him, and he needs no password */
  3181.         if (sstelnet)
  3182.             strcpy(uidbuf,szUserNameRequested);
  3183.         break;
  3184.     }
  3185. }
  3186.  
  3187. #ifdef KRB4
  3188. #ifdef NT
  3189. void
  3190. ck_krb4_debug(int x)
  3191. {
  3192.     set_krb_debug(x);
  3193.     set_krb_ap_req_debug(x);
  3194. }
  3195. #endif /* NT */
  3196. int
  3197. ck_krb4_autoget_TGT(char * realm)
  3198. {
  3199.     extern struct krb_op_data krb_op;
  3200.     extern struct krb4_init_data krb4_init;
  3201.     char passwd[PWD_SZ];
  3202.     char prompt[256];
  3203.     char * saverealm=NULL;
  3204.     int  rc = -1;
  3205.     extern char * k4prprompt;
  3206.     extern char * k4pwprompt;
  3207.  
  3208.     ini_kerb();         /* Place defaults in above structs */
  3209.     passwd[0] = '\0';
  3210.  
  3211.     if ( krb4_init.principal == NULL ||
  3212.          krb4_init.principal[0] == '\0') {
  3213.         readtext(k4prprompt && k4prprompt[0] ?
  3214.          k4prprompt :
  3215.          "Kerberos 4 Principal: ",
  3216.          passwd,PWD_SZ-1);
  3217.         if ( passwd[0] )
  3218.             makestr(&krb4_init.principal,passwd);
  3219.         else
  3220.             return(0);
  3221.     }
  3222.  
  3223.     /* Save realm in init structure so it can be restored */
  3224.     if ( realm ) {
  3225.         saverealm = krb4_init.realm;
  3226.         krb4_init.realm = realm;
  3227.     }
  3228.  
  3229.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  3230.         sprintf(prompt,k4pwprompt && k4pwprompt[0] ? k4pwprompt :
  3231.                  "%s@%s's Kerberos 4 Password: ",
  3232.                  krb4_init.principal,krb4_init.realm);
  3233.         readpass(prompt,passwd,PWD_SZ-1);
  3234.     } else {
  3235.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  3236. #ifdef OS2
  3237.         if ( pwcrypt )
  3238.             ck_encrypt((char *)passwd);
  3239. #endif /* OS2 */
  3240.     }
  3241.  
  3242.     if ( passwd[0] ) {
  3243.         makestr(&krb4_init.password,passwd);
  3244.         rc = ck_krb4_initTGT(&krb_op, &krb4_init);
  3245.         free(krb4_init.password);
  3246.         krb4_init.password = NULL;
  3247.     }
  3248.  
  3249.     krb4_init.password = NULL;
  3250.     memset(passwd,0,PWD_SZ);
  3251.  
  3252.     /* restore realm to init structure if needed */
  3253.     if ( saverealm )
  3254.         krb4_init.realm = saverealm;
  3255.     return(rc == 0);
  3256. }
  3257.  
  3258. char *
  3259. ck_krb4_realmofhost(char *host)
  3260. {
  3261.     return (char *)krb_realmofhost(host);
  3262. }
  3263.  
  3264. /*
  3265.  *
  3266.  * K4_auth_send - gets authentication bits we need to send to KDC.
  3267.  *
  3268.  * Result is left in auth
  3269.  *
  3270.  * Returns: 0 on failure, 1 on success
  3271.  */
  3272. static int
  3273. #ifdef CK_ANSIC
  3274. k4_auth_send(void)
  3275. #else
  3276. k4_auth_send()
  3277. #endif
  3278. {
  3279.     int r=0;                                    /* Return value */
  3280.     char instance[INST_SZ+1]="";
  3281.     char *realm=NULL;
  3282.     char tgt[4*REALM_SZ+1];
  3283.  
  3284.     memset(instance, 0, sizeof(instance));
  3285.  
  3286.     debug(F110,"k4_auth_send","krb_get_phost",0);
  3287.     if (realm = (char *)krb_get_phost(szHostName)) {
  3288.         ckstrncpy(instance, realm, INST_SZ);
  3289.     }
  3290.  
  3291.     debug(F110,"k4_auth_send","krb_get_realmofhost",0);
  3292.     realm = (char *)krb_realmofhost(szHostName);
  3293.  
  3294.     if (!realm) {
  3295.         strcpy(strTmp, "Can't find realm for host \"");
  3296.         strcat(strTmp, szHostName);
  3297.         strcat(strTmp, "\"");
  3298.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3299.         krb4_errno = r;
  3300.         makestr(&krb4_errmsg,strTmp);
  3301.         return(0);
  3302.     }
  3303.  
  3304.     sprintf(tgt,"krbtgt.%s@%s",realm,realm);
  3305.     r = ck_krb4_tkt_isvalid(tgt);
  3306.  
  3307.     if ( r <= 0 && krb4_autoget )
  3308.         ck_krb4_autoget_TGT(realm);
  3309.  
  3310.     debug(F110,"k4_auth_send","krb_mk_req",0);
  3311.     r = krb_mk_req(&k4_auth, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3312.                     instance, realm, 0);
  3313.  
  3314.     if (r == 0) {
  3315.         debug(F110,"k4_auth_send","krb_get_cred",0);
  3316.         r = krb_get_cred(krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3317.                           instance, realm, (CREDENTIALS *)&cred);
  3318.         if (r)
  3319.             debug(F111,"k4_auth_send","krb_get_cred() failed",r);
  3320.     }
  3321.     else
  3322.         debug(F111,"k4_auth_send","krb_mk_req() failed",r);
  3323.  
  3324.     if (r) {
  3325.         strcpy(strTmp, "Can't get \"");
  3326.         strcat(strTmp, krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME);
  3327.         if (instance[0] != 0) {
  3328.             strcat(strTmp, ".");
  3329.             strcat(strTmp, instance);
  3330.         }
  3331.         strcat(strTmp, "@");
  3332.         strcat(strTmp, realm);
  3333.         strcat(strTmp, "\" ticket\r\n  ");
  3334.         strcat(strTmp, (char *)krb_get_err_text_entry(r));
  3335.         debug(F111,"k4_auth_send",(char *)krb_get_err_text_entry(r),r);
  3336.         printf("?Kerberos 4 error: %s\r\n",strTmp);
  3337.         krb4_errno = r;
  3338.         makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3339.         return(0);
  3340.     }
  3341.  
  3342. #ifdef OS2
  3343.     if ( !szUserName[0] || !stricmp(szUserName,cred.pname) ) {
  3344.         ckstrncpy(szUserName, cred.pname, UIDBUFLEN);
  3345.     }
  3346. #endif /* OS2 */
  3347.     krb4_errno = r;
  3348.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3349.     debug(F110,"k4_auth_send",krb4_errmsg,0);
  3350.     return(1);
  3351. }
  3352.  
  3353. /*
  3354.  * Function: K4 parse authentication reply command
  3355.  *
  3356.  * Parameters:
  3357.  *  parsedat - the sub-command data.
  3358.  *
  3359.  *  end_sub - index of the character in the 'parsedat' array which
  3360.  *        is the last byte in a sub-negotiation
  3361.  *
  3362.  * Returns: Kerberos error code.
  3363.  */
  3364. static int
  3365. #ifdef CK_ANSIC
  3366. k4_auth_reply(unsigned char *parsedat, int end_sub)
  3367. #else
  3368. k4_auth_reply(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3369. #endif
  3370. {
  3371. #ifdef CK_ENCRYPTION
  3372.     Session_Key skey;
  3373. #ifdef MIT_CURRENT
  3374.     krb5_data kdata;
  3375.     krb5_enc_data encdata;
  3376.     krb5_error_code code;
  3377. #endif /* MIT_CURRENT */
  3378. #endif
  3379.     time_t t;
  3380.     int x;
  3381.     int i;
  3382.  
  3383.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  3384.         auth_finished(AUTH_REJECT);
  3385.         return AUTH_FAILURE;
  3386.     }
  3387.  
  3388.     if (parsedat[4] == KRB_REJECT) {
  3389.         strTmp[0] = 0;
  3390.  
  3391.         for (i = 5; i <= end_sub; i++) {
  3392.             if (parsedat[i] == IAC)
  3393.                 break;
  3394.             strTmp[i-5] = parsedat[i];
  3395.             strTmp[i-4] = 0;
  3396.         }
  3397.  
  3398.         if (!strTmp[0])
  3399.             strcpy(strTmp, "Authentication rejected by remote machine!");
  3400.         printf("Kerberos V4 authentication failed!\r\n%s\r\n",strTmp);
  3401.         krb4_errno = 0;
  3402.         makestr(&krb4_errmsg,strTmp);
  3403.         auth_finished(AUTH_REJECT);
  3404.         return AUTH_FAILURE;
  3405.     }
  3406.  
  3407.     if (parsedat[4] == KRB_ACCEPT) {
  3408.         int net_len;
  3409.         if ((parsedat[3] & AUTH_HOW_MASK) == AUTH_HOW_ONE_WAY) {
  3410.             sprintf(strTmp,"Kerberos V4 accepts you as %s",szUserName);
  3411.             printf("%s\r\n",strTmp);
  3412.             accept_complete = 1;
  3413.             krb4_errno = 0;
  3414.             makestr(&krb4_errmsg,strTmp);
  3415.             auth_finished(AUTH_USER);
  3416.             return AUTH_SUCCESS;
  3417.         }
  3418.  
  3419.         if ((parsedat[3] & AUTH_HOW_MASK) != AUTH_HOW_MUTUAL) {
  3420.             printf("Kerberos V4 authentication failed!\r\n");
  3421.             sprintf(strTmp,
  3422.         "Kerberos V4 accepted you, but didn't provide mutual authentication");
  3423.             printf("%s\r\n",strTmp);
  3424.             krb4_errno = 0;
  3425.             makestr(&krb4_errmsg,strTmp);
  3426.             auth_finished(AUTH_REJECT);
  3427.             return AUTH_FAILURE;
  3428.         }
  3429.  
  3430. #ifndef REMOVE_FOR_EXPORT
  3431. #ifdef CK_ENCRYPTION
  3432.         SendK4AuthSB(KRB4_CHALLENGE,k4_session_key,sizeof(k4_session_key));
  3433.  
  3434.         /* We have sent the decrypted session key to the host as a challenge */
  3435.     /* now encrypt it to restore it to its original valid DES key value */
  3436. #ifdef MIT_CURRENT
  3437.         kdata.data = k4_session_key;
  3438.         kdata.length = 8;
  3439.  
  3440.         encdata.ciphertext.data = k4_session_key;
  3441.         encdata.ciphertext.length = 8;
  3442.         encdata.enctype = ENCTYPE_UNKNOWN;
  3443.  
  3444.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey,
  3445.                                    0, 0, &kdata, &encdata)) {
  3446.             com_err("k4_auth_reply", code,
  3447.                      "while encrypting session_key");
  3448.             auth_finished(AUTH_REJECT);
  3449.             return AUTH_FAILURE;
  3450.         }
  3451. #else /* MIT_CURRENT */
  3452. #ifdef NT
  3453.         des_ecb_encrypt(k4_session_key, k4_session_key, k4_sched, 1);
  3454. #else /* NT */
  3455.         des_ecb_encrypt(&k4_session_key, &k4_session_key, k4_sched, 1);
  3456. #endif /* NT */
  3457.         hexdump(
  3458.         "k4_auth_reply des_ecb_encrypt(k4_session_key,k4_session_key,1)",
  3459.              k4_session_key,
  3460.          8
  3461.         );
  3462. #endif /* MIT_CURRENT */
  3463.  
  3464.         /* And then use it to configure the encryption state machine. */
  3465.         skey.type = SK_DES;
  3466.         skey.length = 8;
  3467.         skey.data = k4_session_key;
  3468.         encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  3469. #endif /* ENCRYPTION */
  3470. #endif /* REMOVE_FOR_EXPORT */
  3471.         accept_complete = 1;
  3472.         sprintf(strTmp,"Kerberos V4 accepts you as %s",szUserName);
  3473.         printf("%s\r\n",strTmp);
  3474.         krb4_errno = 0;
  3475.         makestr(&krb4_errmsg,strTmp);
  3476.         auth_finished(AUTH_USER);
  3477.         return AUTH_SUCCESS;
  3478.     }
  3479.  
  3480.     if (parsedat[4] == KRB4_RESPONSE) {
  3481.         if (end_sub < 12) {
  3482.             auth_finished(AUTH_REJECT);
  3483.             return AUTH_FAILURE;
  3484.         }
  3485.  
  3486.         hexdump("KRB4_RESPONSE &parsedat[5]",&parsedat[5],8);
  3487. #ifdef CK_ENCRYPTION
  3488.         hexdump("KRB4_RESPONSE k4_challenge",k4_challenge,8);
  3489.  
  3490.         /* The datablock returned from the host should match the value */
  3491.         /* we stored in k4_challenge.                                  */
  3492.         if (memcmp(&parsedat[5], k4_challenge, sizeof(k4_challenge)) != 0) {
  3493.             printf("Kerberos V4 authentication failed!\r\n%s\r\n",
  3494.             "Remote machine is being impersonated!");
  3495.             krb4_errno = 0;
  3496.             makestr(&krb4_errmsg,"Remote machine is being impersonated!");
  3497.             auth_finished(AUTH_REJECT);
  3498.             return AUTH_FAILURE;
  3499.         }
  3500. #else /* ENCRYPTION */
  3501.         makestr(&krb4_errmsg,"Kermit built without support for encryption.");
  3502.         return AUTH_FAILURE;
  3503. #endif /* ENCRYPTION */
  3504.         mutual_complete = 1;
  3505.         sprintf(strTmp,"Remote machine has been mutually authenticated");
  3506.         printf("%s\r\n",strTmp);
  3507.         krb4_errno = 0;
  3508.         makestr(&krb4_errmsg,strTmp);
  3509.         auth_finished(AUTH_USER);
  3510.         return AUTH_SUCCESS;
  3511.     }
  3512.     auth_finished(AUTH_REJECT);
  3513.     return AUTH_FAILURE;
  3514. }
  3515.  
  3516. /*
  3517.  * Function: K4 parse authentication IS command
  3518.  *
  3519.  * Parameters:
  3520.  *  parsedat - the sub-command data.
  3521.  *
  3522.  *  end_sub - index of the character in the 'parsedat' array which
  3523.  *            is the last byte in a sub-negotiation
  3524.  *
  3525.  * Returns: Kerberos error code.
  3526.  */
  3527.  
  3528. static int
  3529. #ifdef CK_ANSIC
  3530. k4_auth_is(unsigned char *parsedat, int end_sub)
  3531. #else
  3532. k4_auth_is(parsedat,end_sub) unsigned char *parsedat; int end_sub;
  3533. #endif
  3534. {
  3535. #ifdef CK_ENCRYPTION
  3536.     Session_Key skey;
  3537. #ifdef MIT_CURRENT
  3538.     Block datablock, tmpkey;
  3539.     krb5_data kdata;
  3540.     krb5_enc_data encdata;
  3541.     krb5_error_code code;
  3542. #else /* MIT_CURRENT */
  3543.     Block datablock;
  3544. #endif /* MIT_CURRENT */
  3545. #endif    /* ENCRYPTION */
  3546.     char realm[REALM_SZ+1];
  3547.     char instance[INST_SZ];
  3548.     int r = 0;
  3549.     char * data = &parsedat[5];
  3550.     int    cnt = end_sub - 5;
  3551.     extern char myipaddr[];
  3552.     struct hostent *host;
  3553.     struct in_addr inaddr;
  3554.     int i;
  3555.  
  3556.     if (end_sub < 4 || parsedat[2] != AUTHTYPE_KERBEROS_V4) {
  3557.         debug(F110,"k4_auth_is","Not kerberos v4",0);
  3558.         auth_finished(AUTH_REJECT);
  3559.         return AUTH_FAILURE;
  3560.     }
  3561.  
  3562.     switch (parsedat[4]) {
  3563.     case KRB_AUTH:
  3564.         debug(F110,"k4_auth_is","KRB_AUTH",0);
  3565.         if (krb_get_lrealm(realm, 1) != KSUCCESS) {
  3566.             SendK4AuthSB(KRB_REJECT, (void *)"No local V4 Realm.", -1);
  3567.             printf("\r\n? Kerberos 4 - No Local Realm\r\n");
  3568.             debug(F110,"k4_auth_is","No local realm",0);
  3569.             krb4_errno = 0;
  3570.             makestr(&krb4_errmsg,"No local realm");
  3571.             auth_finished(AUTH_REJECT);
  3572.             return AUTH_FAILURE;
  3573.         }
  3574.         debug(F110,"k4_auth_is",realm,0);
  3575.         k4_auth.length = cnt;
  3576.         memcpy((void *)k4_auth.dat, (void *)data, k4_auth.length);
  3577. #ifdef COMMENT
  3578.         debug(F101,"kerberos4_cksum","",
  3579.                kerberos4_cksum(k4_auth.dat, k4_auth.length));
  3580. #endif /* COMMENT */
  3581.         hexdump("k4_auth.dat",k4_auth.dat, k4_auth.length);
  3582.  
  3583.         /* Get Instance */
  3584.         inaddr.s_addr = inet_addr(myipaddr);
  3585.         host = gethostbyaddr((unsigned char *)&inaddr,4,PF_INET);
  3586.         if ( host ) {
  3587.             ckstrncpy(instance,host->h_name,INST_SZ);
  3588.             for ( i=0;i<INST_SZ;i++ ) {
  3589.                 if ( instance[i] == '.' )
  3590.                     instance[i] = '\0';
  3591.                 else
  3592.                     instance[i] = tolower(instance[i]);
  3593.             }
  3594.         } else {
  3595.             instance[0] = '*';
  3596.             instance[1] = 0;
  3597.         }
  3598.  
  3599.         if (r = krb_rd_req(&k4_auth,
  3600.                             krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  3601.                             instance, 0, &k4_adat, k4_keyfile)) {
  3602.  
  3603.             hexdump("k4_adat", &k4_adat, sizeof(AUTH_DAT));
  3604.             krb_kntoln(&k4_adat, k4_name);
  3605.             sprintf(strTmp,"Kerberos failed him as %s", k4_name);
  3606.             printf("%s\r\n",strTmp);
  3607.             krb4_errno = r;
  3608.             makestr(&krb4_errmsg,strTmp);
  3609.             SendK4AuthSB(KRB_REJECT, (void *)krb_get_err_text_entry(r), -1);
  3610.             auth_finished(AUTH_REJECT);
  3611.             return AUTH_FAILURE;
  3612.         }
  3613.  
  3614. #ifdef CK_ENCRYPTION
  3615.         memcpy((void *)k4_session_key, (void *)k4_adat.session, sizeof(Block));
  3616.         hexdump("k4_auth_is k4_session_key",k4_session_key,sizeof(Block));
  3617. #endif /* ENCRYPTION */
  3618.         krb_kntoln(&k4_adat, k4_name);
  3619.  
  3620.         ckstrncpy(szUserNameAuthenticated,k4_name,128);
  3621.         if (szUserNameRequested && !kuserok(&k4_adat, k4_name)) {
  3622.             SendK4AuthSB(KRB_ACCEPT, (void *)0, 0);
  3623.         if ( !strcmp(k4_name,szUserNameRequested) )
  3624.         auth_finished(AUTH_VALID);
  3625.         else
  3626.         auth_finished(AUTH_USER);
  3627.             accept_complete = 1;
  3628.         }
  3629.         else {
  3630.             SendK4AuthSB(KRB_REJECT,
  3631.                   (void *)"user is not authorized", -1);
  3632.             auth_finished(AUTH_REJECT);
  3633.             krb4_errno = r;
  3634.             makestr(&krb4_errmsg,"user is not authorized");
  3635.             return(AUTH_FAILURE);
  3636.         }
  3637.         break;
  3638.  
  3639.     case KRB4_CHALLENGE:
  3640.         debug(F110,"k4_auth_is","KRB_CHALLENGE",0);
  3641. #ifndef CK_ENCRYPTION
  3642.         SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  3643. #else    /* ENCRYPTION */
  3644.         if (!VALIDKEY(k4_session_key)) {
  3645.             /*
  3646.             * We don't have a valid session key, so just
  3647.             * send back a response with an empty session
  3648.             * key.
  3649.             */
  3650.             SendK4AuthSB(KRB4_RESPONSE, (void *)0, 0);
  3651.             mutual_complete = 1;
  3652.             break;
  3653.         }
  3654.  
  3655.         /*
  3656.         * Initialize the random number generator since it's
  3657.         * used later on by the encryption routine.
  3658.         */
  3659. #ifdef MIT_CURRENT
  3660.         kdata.data = k4_session_key;
  3661.         kdata.length = 8;
  3662.  
  3663.         if (code = krb5_c_random_seed(k5_context, &kdata)) {
  3664.             com_err("k4_auth_is", code,
  3665.                      "while seeding random number generator");
  3666.             auth_finished(AUTH_REJECT);
  3667.             return AUTH_FAILURE;
  3668.         }
  3669.  
  3670.         memcpy((void *)datablock, (void *)data, sizeof(Block));
  3671.         /*
  3672.         * Take the received encrypted challenge, and encrypt
  3673.         * it again to get a unique session_key for the
  3674.         * ENCRYPT option.
  3675.         */
  3676.         k4_krbkey.enctype = ENCTYPE_DES_CBC_RAW;
  3677.         k4_krbkey.length = 8;
  3678.         k4_krbkey.contents = k4_session_key;
  3679.  
  3680.         kdata.data = datablock;
  3681.         kdata.length = 8;
  3682.  
  3683.         encdata.ciphertext.data = tmpkey;
  3684.         encdata.ciphertext.length = 8;
  3685.         encdata.enctype = ENCTYPE_UNKNOWN;
  3686.  
  3687.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  3688.                                    &kdata, &encdata)) {
  3689.             com_err("k4_auth_is", code, "while encrypting random key");
  3690.             auth_finished(AUTH_REJECT);
  3691.             return AUTH_FAILURE;
  3692.         }
  3693.  
  3694.         skey.type = SK_DES;
  3695.         skey.length = 8;
  3696.         skey.data = tmpkey;
  3697.         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  3698.         /*
  3699.         * Now decrypt the received encrypted challenge,
  3700.         * increment by one, re-encrypt it and send it back.
  3701.         */
  3702.         encdata.ciphertext.data = datablock;
  3703.         encdata.ciphertext.length = 8;
  3704.         encdata.enctype = ENCTYPE_UNKNOWN;
  3705.  
  3706.         kdata.data = k4_challenge;
  3707.         kdata.length = 8;
  3708.  
  3709.         if (code = krb5_c_decrypt(k5_context, &k4_krbkey, 0, 0,
  3710.                                    &encdata, &kdata)) {
  3711.             com_err("k4_auth_is", code, "while decrypting challenge");
  3712.             auth_finished(AUTH_REJECT);
  3713.             return AUTH_FAILURE;
  3714.         }
  3715. #else /* MIT_CURRENT */
  3716.         des_set_random_generator_seed(k4_session_key);
  3717.         r = des_key_sched(k4_session_key, k4_sched);
  3718.         if ( r == -1 ) {
  3719.             printf("?Invalid DES key specified in credentials\r\n");
  3720.             debug(F110,"auth_is CHALLENGE",
  3721.                    "invalid DES Key specified in credentials",0);
  3722.         } else if ( r == -2 ) {
  3723.             printf("?Weak DES key specified in credentials\r\n");
  3724.             debug(F110,"auth_is CHALLENGE",
  3725.                    "weak DES Key specified in credentials",0);
  3726.         } else if ( r != 0 ) {
  3727.             printf("?DES Key Schedule not set by credentials\r\n");
  3728.             debug(F110,"auth_is CHALLENGE",
  3729.                    "DES Key Schedule not set by credentials",0);
  3730.         }
  3731.         hexdump("auth_is schedule",k4_sched,8*16);
  3732.  
  3733.         memcpy((void *)datablock, (void *)data, sizeof(Block));
  3734.         hexdump("auth_is challege",datablock,sizeof(Block));
  3735.  
  3736.         /*
  3737.         * Take the received encrypted challenge, and encrypt
  3738.         * it again to get a unique k4_session_key for the
  3739.         * ENCRYPT option.
  3740.         */
  3741. #ifdef NT
  3742.         des_ecb_encrypt(datablock, k4_session_key, k4_sched, 1);
  3743. #else /* NT */
  3744.         des_ecb_encrypt(&datablock, &k4_session_key, k4_sched, 1);
  3745. #endif /* NT */
  3746.         hexdump("auth_is des_ecb_encrypt(datablock,k4_session_key,1)",
  3747.                  k4_session_key,8);
  3748.  
  3749.         skey.type = SK_DES;
  3750.         skey.length = 8;
  3751.         skey.data = k4_session_key;
  3752.         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  3753.         /*
  3754.         * Now decrypt the received encrypted challenge,
  3755.         * increment by one, re-encrypt it and send it back.
  3756.         */
  3757. #ifdef NT
  3758.         des_ecb_encrypt(datablock, k4_challenge, k4_sched, 0);
  3759. #else /* NT */
  3760.         des_ecb_encrypt(&datablock, &k4_challenge, k4_sched, 0);
  3761. #endif /* NT */
  3762.         hexdump("auth_is des_ecb_encrypt(datablock,k4_challenge,0)",
  3763.                  k4_session_key,8);
  3764. #endif /* MIT_CURRENT */
  3765.         for (r = 7; r >= 0; r--) {
  3766.             register int t;
  3767.             t = (unsigned int)k4_challenge[r] + 1;
  3768.             k4_challenge[r] = t;    /* ignore overflow */
  3769.             if (t < 256)        /* if no overflow, all done */
  3770.                 break;
  3771.         }
  3772.         hexdump("auth_is k4_challenge+1",k4_challenge,8);
  3773.  
  3774. #ifdef MIT_CURRENT
  3775.         kdata.data = k4_challenge;
  3776.         kdata.length = 8;
  3777.  
  3778.         encdata.ciphertext.data = k4_challenge;
  3779.         encdata.ciphertext.length = 8;
  3780.         encdata.enctype = ENCTYPE_UNKNOWN;
  3781.  
  3782.         if (code = krb5_c_encrypt(k5_context, &k4_krbkey, 0, 0,
  3783.                                    &kdata, &encdata)) {
  3784.             com_err("k4_auth_is", code, "while decrypting challenge");
  3785.             auth_finished(AUTH_REJECT);
  3786.             return AUTH_FAILURE;
  3787.         }
  3788. #else /* MIT_CURRENT */
  3789. #ifdef NT
  3790.         des_ecb_encrypt(k4_challenge, k4_challenge, k4_sched, 1);
  3791. #else /* NT */
  3792.         des_ecb_encrypt(&k4_challenge, &k4_challenge, k4_sched, 1);
  3793. #endif /* NT */
  3794.         hexdump("auth_is des_ecb_encrypt(k4_challenge_key,k4_challenge,1)",
  3795.                  k4_challenge,8);
  3796.  
  3797. #endif /* MIT_CURRENT */
  3798.         SendK4AuthSB(KRB4_RESPONSE,(void *)k4_challenge,sizeof(k4_challenge));
  3799. #endif    /* ENCRYPTION */
  3800.         mutual_complete = 1;
  3801.         break;
  3802.  
  3803.     default:
  3804.         if (1)
  3805.             printf("Unknown Kerberos option %d\r\n", data[-1]);
  3806.         SendK4AuthSB(KRB_REJECT, 0, 0);
  3807.         return(AUTH_FAILURE);
  3808.     }
  3809.     krb4_errno = r;
  3810.     makestr(&krb4_errmsg,krb_get_err_text_entry(krb4_errno));
  3811.     return(AUTH_SUCCESS);
  3812. }
  3813. #endif /* KRB4 */
  3814.  
  3815. #ifdef KRB5
  3816. int
  3817. ck_krb5_autoget_TGT(char * realm)
  3818. {
  3819.     extern struct krb_op_data krb_op;
  3820.     extern struct krb5_init_data krb5_init;
  3821.     char passwd[PWD_SZ];
  3822.     char prompt[64];
  3823.     char * saverealm=NULL;
  3824.     int  rc = -1;
  3825.     extern char * k5prprompt;
  3826.     extern char * k5pwprompt;
  3827.  
  3828.     ini_kerb();         /* Place defaults in above structs */
  3829.     passwd[0] = '\0';
  3830.  
  3831.     if ( krb5_init.principal == NULL ||
  3832.          krb5_init.principal[0] == '\0') {
  3833.         readtext(k5prprompt && k5prprompt[0] ? k5prprompt :
  3834.                   "Kerberos 5 Principal: ",passwd,PWD_SZ-1);
  3835.         if ( passwd[0] )
  3836.             makestr(&krb5_init.principal,passwd);
  3837.         else
  3838.             return(0);
  3839.     }
  3840.  
  3841.     /* Save realm in init structure so it can be restored */
  3842.     if ( realm ) {
  3843.         saverealm = krb5_init.realm;
  3844.         krb5_init.realm = realm;
  3845.     }
  3846.  
  3847.     if ( passwd[0] || !(pwbuf[0] && pwflg) ) {
  3848.         sprintf(prompt,k5pwprompt && k5pwprompt[0] ? k5pwprompt :
  3849.                  "%s@%s's Kerberos 5 Password: ",
  3850.                  krb5_init.principal,krb5_init.realm);
  3851.         readpass(prompt,passwd,PWD_SZ-1);
  3852.     } else {
  3853.         ckstrncpy(passwd,pwbuf,sizeof(passwd));
  3854. #ifdef OS2
  3855.         if ( pwcrypt )
  3856.             ck_encrypt((char *)passwd);
  3857. #endif /* OS2 */
  3858.     }
  3859.  
  3860.     if ( passwd[0] ) {
  3861.         makestr(&krb5_init.password,passwd);
  3862.         rc = ck_krb5_initTGT(&krb_op, &krb5_init);
  3863.         free(krb5_init.password);
  3864.         krb5_init.password = NULL;
  3865.  
  3866.         if ( krb5_d_getk4 && krb4_autoget ) {
  3867.             extern struct krb4_init_data krb4_init;
  3868.             char * savek4realm=NULL;
  3869.  
  3870.             makestr(&krb4_init.principal,krb5_init.principal);
  3871.             makestr(&krb4_init.password,passwd);
  3872.             if ( realm ) {
  3873.                 savek4realm = krb4_init.realm;
  3874.                 krb4_init.realm = realm;
  3875.             }
  3876.             rc = ck_krb4_initTGT(&krb_op, &krb4_init);
  3877.             if ( savek4realm )
  3878.                 krb4_init.realm = savek4realm;
  3879.             free(krb4_init.password);
  3880.             krb4_init.password = NULL;
  3881.         }
  3882.         memset(passwd,0,PWD_SZ);
  3883.     }
  3884.  
  3885.     /* restore realm to init structure if needed */
  3886.     if ( saverealm )
  3887.         krb5_init.realm = saverealm;
  3888.     return(rc == 0);
  3889. }
  3890.  
  3891. static krb5_error_code
  3892. #ifdef CK_ANSIC
  3893. k5_get_ccache( krb5_context k5_context, krb5_ccache * p_ccache,
  3894.                char * cc_name )
  3895. #else  /* CK_ANSIC */
  3896. k5_get_ccache(k5_context, p_ccache, cc_name)
  3897.     krb5_context k5_context;
  3898.     krb5_ccache * p_ccache;
  3899.     char * cc_name;
  3900. #endif /* CK_ANSIC */
  3901. {
  3902.     krb5_error_code r=0;
  3903.     char cc_tmp[CKMAXPATH+1];
  3904.     const char * def_name = NULL;
  3905.  
  3906.     if ( cc_name ) {
  3907.         if ( strncmp("FILE:",cc_name,5) &&
  3908.              strncmp("MEMORY:",cc_name,7) &&
  3909.              strncmp("API:",cc_name,4) &&
  3910.              strncmp("STDIO:",cc_name,6))
  3911.             sprintf(cc_tmp,"FILE:%s",cc_name);
  3912.         else {
  3913.             ckstrncpy(cc_tmp,cc_name,CKMAXPATH);
  3914.         }
  3915.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  3916.         if (r != 0) {
  3917.             com_err("k5_get_ccache resolving ccache",r,
  3918.                      cc_tmp);
  3919.         }
  3920.     } else if ( krb5_d_cc ) {
  3921.         if ( strncmp("FILE:",krb5_d_cc,5) &&
  3922.              strncmp("MEMORY:",krb5_d_cc,7) &&
  3923.              strncmp("API:",krb5_d_cc,4) &&
  3924.              strncmp("STDIO:",krb5_d_cc,6))
  3925.             sprintf(cc_tmp,"FILE:%s",krb5_d_cc);
  3926.         else {
  3927.             ckstrncpy(cc_tmp,krb5_d_cc,CKMAXPATH);
  3928.         }
  3929.         r = krb5_cc_resolve (k5_context, cc_tmp, p_ccache);
  3930.         if (r != 0) {
  3931.             com_err("k5_get_ccache resolving ccache",r,
  3932.                      krb5_d_cc);
  3933.         }
  3934.     } else {
  3935.         if ((r = krb5_cc_default(k5_context, p_ccache))) {
  3936.             com_err("k5_get_ccache",r,"while getting default ccache");
  3937.         }
  3938.     }
  3939.     krb5_errno = r;
  3940.     makestr(&krb5_errmsg,error_message(krb5_errno));
  3941.     return(r);
  3942. }
  3943.  
  3944.  
  3945. char *
  3946. ck_krb5_realmofhost(char *host)
  3947. {
  3948.     char ** realmlist=NULL;
  3949.     krb5_context private_context=NULL;
  3950.     static char * realm = NULL;
  3951.  
  3952.     if ( !host )
  3953.         return NULL;
  3954.  
  3955.     if ( realm ) {
  3956.         free(realm);
  3957.         realm = NULL;
  3958.     }
  3959.  
  3960.     /* create private_context */
  3961.     krb5_init_context(&private_context);
  3962.  
  3963.     krb5_get_host_realm(private_context,host,&realmlist);
  3964.     if (realmlist && realmlist[0]) {
  3965.         makestr(&realm,realmlist[0]);
  3966.         krb5_free_host_realm(private_context,realmlist);
  3967.         realmlist = NULL;
  3968.     }
  3969.  
  3970.     if ( private_context ) {
  3971.         krb5_free_context(private_context);
  3972.         private_context = NULL;
  3973.     }
  3974.  
  3975.     return(realm);
  3976. }
  3977.  
  3978. /*
  3979.  *
  3980.  * K5_auth_send - gets authentication bits we need to send to KDC.
  3981.  *
  3982.  * Code lifted from telnet sample code in the appl directory.
  3983.  *
  3984.  * Result is left in k5_auth
  3985.  *
  3986.  * Returns: 0 on failure, 1 on success
  3987.  *
  3988.  */
  3989.  
  3990. static int
  3991. #ifdef CK_ANSIC
  3992. k5_auth_send(int how, int encrypt, int forward)
  3993. #else
  3994. k5_auth_send(how,encrypt) int how; int encrypt; int forward;
  3995. #endif
  3996. {
  3997.     krb5_error_code r=0;
  3998.     krb5_ccache ccache=NULL;
  3999.     krb5_creds creds;
  4000.     krb5_creds * new_creds=NULL;
  4001.     krb5_flags ap_opts;
  4002.     char type_check[2];
  4003.     krb5_data check_data;
  4004.     int len=0;
  4005. #ifdef CK_ENCRYPTION
  4006.     krb5_keyblock *newkey = 0;
  4007. #endif
  4008.     char * realm = NULL;
  4009.     char tgt[256];
  4010.  
  4011.  
  4012.     realm = ck_krb5_realmofhost(szHostName);
  4013.     if (!realm) {
  4014.         strcpy(strTmp, "Can't find realm for host \"");
  4015.         strcat(strTmp, szHostName);
  4016.         strcat(strTmp, "\"");
  4017.         printf("?Kerberos 5 error: %s\r\n",strTmp);
  4018.         krb5_errno = 5;
  4019.         makestr(&krb5_errmsg,strTmp);
  4020.         return(0);
  4021.     }
  4022.  
  4023.     sprintf(tgt,"krbtgt/%s@%s",realm,realm);
  4024.     debug(F110,"k5_auth_send TGT",tgt,0);
  4025.     if (!((ck_krb5_tkt_isvalid(NULL,tgt) > 0) ||
  4026.       (ck_krb5_is_tgt_valid() > 0)) &&
  4027.         krb5_autoget )
  4028.         ck_krb5_autoget_TGT(realm);
  4029.  
  4030.     r = k5_get_ccache(k5_context,&ccache,NULL);
  4031.     if ( r ) {
  4032.         com_err(NULL, r, "while authorizing (0).");
  4033.         krb5_errno = r;
  4034.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4035.         return(0);
  4036.     }
  4037.  
  4038.     memset((char *)&creds, 0, sizeof(creds));
  4039.     if (r = krb5_sname_to_principal(k5_context, szHostName,
  4040.                                 krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4041.                                 KRB5_NT_SRV_HST, &creds.server)) {
  4042.         com_err(NULL, r, "while authorizing (1).");
  4043.         krb5_errno = r;
  4044.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4045.         return(0);
  4046.     }
  4047.  
  4048.     if (r = krb5_cc_get_principal(k5_context, ccache, &creds.client)) {
  4049.         com_err(NULL, r, "while authorizing (2).");
  4050.         krb5_free_cred_contents(k5_context, &creds);
  4051.         krb5_errno = r;
  4052.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4053.         return(0);
  4054.     }
  4055.  
  4056.     if (szUserName[0] == '\0') {                /* Get user name now */
  4057.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4058.         memcpy(szUserName,
  4059.                 krb5_princ_component(k5_context, creds.client, 0)->data,
  4060.                 len);
  4061.         szUserName[len] = '\0';
  4062.     } else {
  4063.         char * name = NULL;
  4064.         len  = krb5_princ_component(k5_context, creds.client, 0)->length;
  4065.         if ( len == strlen(szUserName) ) {
  4066.             name = krb5_princ_component(k5_context, creds.client, 0)->data;
  4067. #ifdef OS2
  4068.             if ( !strnicmp(szUserName,name,len) ) {
  4069.                 memcpy(szUserName,name,len);
  4070.                 szUserName[len] = '\0';
  4071.             }
  4072. #endif /* OS2 */
  4073.         }
  4074.     }
  4075.     creds.keyblock.enctype=ENCTYPE_DES_CBC_CRC;
  4076.     if (r = krb5_get_credentials(k5_context, 0,
  4077.                                   ccache, &creds, &new_creds)) {
  4078.         com_err(NULL, r, "while authorizing (3).");
  4079.         krb5_free_cred_contents(k5_context, &creds);
  4080.         krb5_errno = r;
  4081.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4082.         return(0);
  4083.     }
  4084.  
  4085.     if (auth_context) {
  4086.         krb5_auth_con_free(k5_context, auth_context);
  4087.         auth_context = 0;
  4088.     }
  4089.     if ((r = krb5_auth_con_init(k5_context, &auth_context))) {
  4090.         com_err(NULL, r, "while initializing auth context");
  4091.         krb5_errno = r;
  4092.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4093.         return(0);
  4094.     }
  4095.  
  4096.     krb5_auth_con_setflags(k5_context, auth_context,
  4097.                             KRB5_AUTH_CONTEXT_RET_TIME);
  4098.  
  4099.     type_check[0] = AUTHTYPE_KERBEROS_V5;
  4100.     type_check[1] = AUTH_CLIENT_TO_SERVER |
  4101.         (how ? AUTH_HOW_MUTUAL : AUTH_HOW_ONE_WAY) |
  4102.         (encrypt ? AUTH_ENCRYPT_USING_TELOPT : AUTH_ENCRYPT_OFF) |
  4103.         (forward ? INI_CRED_FWD_ON : INI_CRED_FWD_OFF);
  4104.  
  4105.     check_data.magic = KV5M_DATA;
  4106.     check_data.length = 2;
  4107.     check_data.data = (char *)&type_check;
  4108.  
  4109.     ap_opts = 0;
  4110.     if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
  4111.         ap_opts = AP_OPTS_MUTUAL_REQUIRED;
  4112.  
  4113. #ifdef CK_ENCRYPTION
  4114.     ap_opts |= AP_OPTS_USE_SUBKEY;
  4115. #endif
  4116.  
  4117.     r = krb5_mk_req_extended(k5_context, &auth_context, ap_opts,
  4118.                               &check_data, new_creds, &k5_auth);
  4119.  
  4120. #ifdef CK_ENCRYPTION
  4121.     krb5_auth_con_getlocalsubkey(k5_context, auth_context, &newkey);
  4122.     if (k5_session_key) {
  4123.         krb5_free_keyblock(k5_context, k5_session_key);
  4124.         k5_session_key = 0;
  4125.     }
  4126.  
  4127.     if (newkey) {
  4128.         /*
  4129.         * keep the key in our private storage, but don't use it
  4130.         * yet---see kerberos5_reply() below
  4131.         */
  4132.         if ((newkey->enctype != ENCTYPE_DES_CBC_CRC) &&
  4133.              (newkey-> enctype != ENCTYPE_DES_CBC_MD5))
  4134.         {
  4135.             if ((new_creds->keyblock.enctype == ENCTYPE_DES_CBC_CRC) ||
  4136.                  (new_creds->keyblock.enctype == ENCTYPE_DES_CBC_MD5))
  4137.                 /* use the session key in credentials instead */
  4138.                 krb5_copy_keyblock(k5_context,
  4139.                                     &new_creds->keyblock, &k5_session_key);
  4140.             else
  4141.                 ;     /* What goes here? XXX */
  4142.         } else {
  4143.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4144.         }
  4145.         krb5_free_keyblock(k5_context, newkey);
  4146.     }
  4147. #endif  /* ENCRYPTION */
  4148.  
  4149.     krb5_free_cred_contents(k5_context, &creds);
  4150.     krb5_free_creds(k5_context, new_creds);
  4151.     krb5_cc_close(k5_context,ccache);
  4152.  
  4153.     if (r) {
  4154.         com_err(NULL, r, "while authorizing (4).");
  4155.         krb5_errno = r;
  4156.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4157.         return(0);
  4158.     }
  4159.     krb5_errno = r;
  4160.     makestr(&krb5_errmsg,error_message(krb5_errno));
  4161.     return(1);
  4162. }
  4163.  
  4164. /*
  4165.  *
  4166.  * K5_auth_reply -- checks the reply for mutual authentication.
  4167.  *
  4168.  * Code lifted from telnet sample code in the appl directory.
  4169.  *
  4170.  */
  4171. static int
  4172. #ifdef CK_ANSIC
  4173. k5_auth_reply(int how, unsigned char *data, int cnt)
  4174. #else
  4175. k5_auth_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  4176. #endif
  4177. {
  4178. #ifdef CK_ENCRYPTION
  4179.     Session_Key skey;
  4180. #endif
  4181.  
  4182.     data += 4;                                  /* Point to status byte */
  4183.  
  4184.     switch (*data++) {
  4185.     case KRB_REJECT:
  4186.         cnt -=5;
  4187.         if (cnt > 0) {
  4188.             char *s;
  4189.             sprintf(strTmp,"Kerberos V5 refuses authentication because\r\n");
  4190.             s = strTmp + strlen(strTmp);
  4191.             memcpy(s, data, cnt);
  4192.             s[cnt] = 0;
  4193.         } else
  4194.             sprintf(strTmp, "Kerberos V5 refuses authentication");
  4195.         krb5_errno = 0;
  4196.         makestr(&krb5_errmsg,strTmp);
  4197.         printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4198.         auth_finished(AUTH_REJECT);
  4199.         return AUTH_FAILURE;
  4200.  
  4201.     case KRB_ACCEPT:
  4202.         if (!mutual_complete) {
  4203.             if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL && !mutual_complete) {
  4204.                 sprintf(strTmp,
  4205.                           "Kerberos V5 accepted you, but didn't provide"
  4206.                           " mutual authentication");
  4207.                 printf("Kerberos authentication failed!\r\n%s\r\n",strTmp);
  4208.                 krb5_errno = 0;
  4209.                 makestr(&krb5_errmsg,strTmp);
  4210.                 auth_finished(AUTH_REJECT);
  4211.                 return AUTH_FAILURE;
  4212.             }
  4213. #ifdef CK_ENCRYPTION
  4214.             if (k5_session_key) {
  4215.                 skey.type = SK_DES;
  4216.                 skey.length = 8;
  4217.                 skey.data = k5_session_key->contents;
  4218.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4219.             }
  4220. #endif
  4221.         }
  4222.         cnt -= 5;
  4223.         if ( cnt > 0 ) {
  4224.             char *s;
  4225.             sprintf(strTmp,"Kerberos V5 accepts you as ");
  4226.             s = strTmp + strlen(strTmp);
  4227.             memcpy(s,data,cnt);
  4228.             s[cnt] = 0;
  4229.         }
  4230.         accept_complete = 1;
  4231.         printf("%s\r\n",strTmp);
  4232.  
  4233. #ifdef FORWARD
  4234.         if (forward_flag && (auth_how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL)
  4235.             kerberos5_forward();
  4236. #endif
  4237.         krb5_errno = 0;
  4238.         makestr(&krb5_errmsg,strTmp);
  4239.         auth_finished(AUTH_USER);
  4240.         return AUTH_SUCCESS;
  4241.  
  4242.     case KRB5_RESPONSE:
  4243.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  4244.             /* the rest of the reply should contain a krb_ap_rep */
  4245.             krb5_ap_rep_enc_part *reply;
  4246.             krb5_data inbuf;
  4247.             krb5_error_code r;
  4248.  
  4249.             inbuf.length = cnt;
  4250.             inbuf.data = (char *)data;
  4251.  
  4252.             if (r = krb5_rd_rep(k5_context, auth_context, &inbuf, &reply)) {
  4253.                 com_err(NULL, r, "while authorizing. (5)");
  4254.                 krb5_errno = r;
  4255.                 makestr(&krb5_errmsg,error_message(krb5_errno));
  4256.                 auth_finished(AUTH_REJECT);
  4257.                 return AUTH_FAILURE;
  4258.             }
  4259.             krb5_free_ap_rep_enc_part(k5_context, reply);
  4260.  
  4261. #ifdef CK_ENCRYPTION
  4262.             if (encrypt_flag && k5_session_key) {
  4263.                 skey.type = SK_DES;
  4264.                 skey.length = 8;
  4265.                 skey.data = k5_session_key->contents;
  4266.                 encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4267.             }
  4268. #endif /* ENCRYPTION */
  4269.             mutual_complete = 1;
  4270.         }
  4271.         sprintf(strTmp,"Remote machine has been mutually authenticated");
  4272.         krb5_errno = 0;
  4273.         makestr(&krb5_errmsg,strTmp);
  4274.         printf("%s\r\n",strTmp);
  4275.         auth_finished(AUTH_USER);
  4276.         return AUTH_SUCCESS;
  4277.  
  4278. #ifdef FORWARD
  4279.     case KRB5_FORWARD_ACCEPT:
  4280.         forwarded_tickets = 1;
  4281.         sprintf(strTmp,"Remote machine has accepted forwarded credentials");
  4282.         krb5_errno = 0;
  4283.         makestr(&krb5_errmsg,strTmp);
  4284.         printf("%s\r\n",strTmp);
  4285.         return AUTH_SUCCESS;
  4286.  
  4287.     case KRB5_FORWARD_REJECT:
  4288.         forwarded_tickets = 0;
  4289.         if (cnt > 0) {
  4290.             char *s;
  4291.  
  4292.             sprintf(strTmp,
  4293.                       "Kerberos V5 refuses forwarded credentials because ");
  4294.             s = strTmp + strlen(strTmp);
  4295.             memcpy(s, data, cnt);
  4296.             s[cnt] = 0;
  4297.         } else
  4298.             sprintf(strTmp, "Kerberos V5 refuses forwarded credentials");
  4299.  
  4300.         printf("%s\r\n",strTmp);
  4301.         krb5_errno = 0;
  4302.         makestr(&krb5_errmsg,strTmp);
  4303.         return AUTH_SUCCESS;
  4304. #endif    /* FORWARD */
  4305.  
  4306.     default:
  4307.         krb5_errno = 0;
  4308.         makestr(&krb5_errmsg,"Unknown reply type");
  4309.         auth_finished(AUTH_REJECT);
  4310.         return AUTH_FAILURE;                        /* Unknown reply type */
  4311.     }
  4312. }
  4313.  
  4314. #ifdef FORWARD
  4315. /* Decode, decrypt and store the forwarded creds in the local ccache. */
  4316. /* Needed for KRB5_FORWARD                                            */
  4317. static krb5_error_code
  4318. rd_and_store_for_creds(context, auth_context, inbuf)
  4319.     krb5_context context;
  4320.     krb5_auth_context auth_context;
  4321.     krb5_data *inbuf;
  4322. {
  4323.     krb5_creds ** creds;
  4324.     krb5_error_code retval;
  4325.     krb5_ccache ccache=NULL;
  4326.  
  4327.     if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
  4328.         return(retval);
  4329.  
  4330.     retval = k5_get_ccache(context,&ccache,NULL);
  4331.     if ( retval )
  4332.         goto cleanup;
  4333.  
  4334.     if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client)))
  4335.         goto cleanup;
  4336.  
  4337.     if ((retval = krb5_cc_store_cred(context, ccache, creds[0])))
  4338.         goto cleanup;
  4339.  
  4340.     if ((retval = krb5_cc_close(context, ccache)))
  4341.         goto cleanup;
  4342.  
  4343. cleanup:
  4344.     krb5_free_tgt_creds(context, creds);
  4345.     krb5_errno = retval;
  4346.     makestr(&krb5_errmsg,error_message(krb5_errno));
  4347.     return retval;
  4348. }
  4349. #endif /* FORWARD */
  4350.  
  4351. /*
  4352.  *
  4353.  * K5_auth_is.
  4354.  *
  4355.  */
  4356.  
  4357. static int
  4358. #ifdef CK_ANSIC
  4359. k5_auth_is(int how, unsigned char *data, int cnt)
  4360. #else
  4361. k5_auth_is(how,data,cnt) int how; unsigned char *data; int cnt;
  4362. #endif
  4363. {
  4364.     int r = 0;
  4365.     krb5_principal server;
  4366.     krb5_keyblock *newkey = NULL;
  4367.     krb5_keytab keytabid = 0;
  4368.     krb5_data outbuf;
  4369. #ifdef CK_ENCRYPTION
  4370.     Session_Key skey;
  4371. #endif
  4372.     char errbuf[128]="";
  4373.     char *name;
  4374.     char *getenv();
  4375.     krb5_data inbuf;
  4376.     krb5_authenticator *authenticator;
  4377.     char princ[256]="";
  4378.     int len;
  4379.  
  4380.     data += 4;                                  /* Point to status byte */
  4381.     cnt -= 4;
  4382.  
  4383.     hexdump("k5_auth_is data",data,cnt);
  4384.  
  4385.     if (cnt-- < 1) {
  4386.         auth_finished(AUTH_REJECT);
  4387.         return AUTH_FAILURE;
  4388.     }
  4389.     switch (*data++) {
  4390.     case KRB_AUTH:
  4391.         k5_auth.data = (char *)data;
  4392.         k5_auth.length = cnt;
  4393.  
  4394.         debug(F110,"k5_auth_is","KRB_AUTH",0);
  4395.         debug(F111,"k5_auth_is","auth_context",auth_context);
  4396.  
  4397.         if (!r && !auth_context) {
  4398.             r = krb5_auth_con_init(k5_context, &auth_context);
  4399.             debug(F111,"k5_auth_is","krb5_auth_con_init",r);
  4400.         }
  4401.  
  4402.         if (!r) {
  4403.             krb5_rcache rcache = NULL;
  4404.  
  4405.             r = krb5_auth_con_getrcache(k5_context, auth_context,
  4406.                                          &rcache);
  4407.             debug(F111,"k5_auth_is","krb5_auth_con_getrcache",r);
  4408.  
  4409.             if (!r && !rcache) {
  4410.                 r = krb5_sname_to_principal(k5_context, 0,
  4411. #ifdef COMMENT
  4412.                                              0, /* changed in KRB5-CURRENT */
  4413. #else /* COMMENT */
  4414.                                              krb5_d_srv ? krb5_d_srv :
  4415.                                              KRB5_SERVICE_NAME,
  4416. #endif /* COMMENT */
  4417.                                              KRB5_NT_SRV_HST, &server);
  4418.                 debug(F111,"k5_auth_is","krb5_sname_to_principal",r);
  4419.  
  4420.                 if (!r) {
  4421.                     r = krb5_get_server_rcache(k5_context,
  4422.                         krb5_princ_component(k5_context, server, 0),
  4423.                                                 &rcache);
  4424.                     debug(F111,"k5_auth_is","krb5_get_server_rcache",r);
  4425.                     krb5_free_principal(k5_context, server);
  4426.                 }
  4427.             }
  4428.             if (!r) {
  4429.                 r = krb5_auth_con_setrcache(k5_context,
  4430.                                              auth_context, rcache);
  4431.                 debug(F111,"k5_auth_is","krb5_auth_con_setrcache",r);
  4432.             }
  4433.         }
  4434.         if (!r && telnet_srvtab) {
  4435.             r = krb5_kt_resolve(k5_context,
  4436.                                  telnet_srvtab, &keytabid);
  4437.             debug(F111,"k5_auth_is","krb5_kt_resolve",r);
  4438.         }
  4439.         if (!r) {
  4440.             r = krb5_rd_req(k5_context, &auth_context, &k5_auth,
  4441.                              NULL, keytabid, NULL, &k5_ticket);
  4442.             debug(F111,"k5_auth_is","krb5_rd_req",r);
  4443.         }
  4444.         if (r) {
  4445.             (void) strcpy(errbuf, "krb5_rd_req failed: ");
  4446.             (void) strcat(errbuf, error_message(r));
  4447.             goto errout;
  4448.         }
  4449.         len = krb5_princ_component(k5_context,k5_ticket->server,0)->length;
  4450.         if (len < 256)
  4451.         {
  4452.             memcpy(princ,krb5_princ_component(k5_context,
  4453.                                            k5_ticket->server,0)->data,len);
  4454.             princ[len] = '\0';
  4455.         }
  4456.         if ( strcmp((krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME), princ) )
  4457.         {
  4458.             debug(F110,"k5_auth_is incorrect service name",princ,0);
  4459.             (void) sprintf( errbuf, "incorrect service name: %s != %s",
  4460.                             (krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME),
  4461.                             princ);
  4462.             goto errout;
  4463.         }
  4464.  
  4465.         r = krb5_auth_con_getauthenticator(k5_context,
  4466.                                             auth_context,
  4467.                                             &authenticator);
  4468.         debug(F111,"k5_auth_is","krb5_auth_con_getauthenticator",r);
  4469.         if (r) {
  4470.             (void) strcpy(errbuf,
  4471.                            "krb5_auth_con_getauthenticator failed: ");
  4472.             (void) strcat(errbuf, error_message(r));
  4473.             goto errout;
  4474.         }
  4475.  
  4476.         if (authenticator->checksum) {
  4477.             char type_check[2];
  4478.             krb5_checksum *cksum = authenticator->checksum;
  4479.             krb5_keyblock *key;
  4480.  
  4481.             type_check[0] = AUTHTYPE_KERBEROS_V5;
  4482.             type_check[1] = how;        /* not broken into parts */
  4483.  
  4484.             r = krb5_auth_con_getkey(k5_context, auth_context,
  4485.                                       &key);
  4486.             debug(F111,"k5_auth_is","krb5_auth_con_getkey",r);
  4487.             if (r) {
  4488.                 (void) strcpy(errbuf, "krb5_auth_con_getkey failed: ");
  4489.                 (void) strcat(errbuf, error_message(r));
  4490.                 goto errout;
  4491.             }
  4492.  
  4493.             r = krb5_verify_checksum(k5_context,
  4494.                                       cksum->checksum_type, cksum,
  4495.                                       &type_check, 2, key->contents,
  4496.                                       key->length);
  4497.             debug(F111,"k5_auth_is","krb5_verify_checksum",r);
  4498.             if (r) {
  4499.                 (void) strcpy(errbuf,
  4500.                                "checksum verification failed: ");
  4501.                 (void) strcat(errbuf, error_message(r));
  4502.                 goto errout;
  4503.             }
  4504.             krb5_free_keyblock(k5_context, key);
  4505.         } else {
  4506.             if ((how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT) {
  4507.                 (void) strcpy(errbuf,
  4508.                                "authenticator is missing required checksum");
  4509.                 goto errout;
  4510.             }
  4511.         }
  4512.  
  4513.         krb5_free_authenticator(k5_context, authenticator);
  4514.         if ((how & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
  4515.             /* do ap_rep stuff here */
  4516.             if ((r = krb5_mk_rep(k5_context, auth_context,
  4517.                                   &outbuf))) {
  4518.                 debug(F111,"k5_auth_is","krb5_mk_rep",r);
  4519.                 (void) strcpy(errbuf, "Make reply failed: ");
  4520.                 (void) strcat(errbuf, error_message(r));
  4521.                 goto errout;
  4522.             }
  4523.             debug(F111,"k5_auth_is","krb5_mk_rep",r);
  4524.  
  4525.             SendK5AuthSB(KRB5_RESPONSE, outbuf.data, outbuf.length);
  4526.             mutual_complete = 1;
  4527.         }
  4528.         if (krb5_unparse_name(k5_context,
  4529.                                k5_ticket->enc_part2 ->client,
  4530.                                &name))
  4531.             name = 0;
  4532.         SendK5AuthSB(KRB_ACCEPT, name, name ? -1 : 0);
  4533.         accept_complete = 1;
  4534.         sprintf(strTmp,"Kerberos5 identifies him as ``%s''",
  4535.                 name ? name : "");
  4536.         printf("%s\r\n",strTmp);
  4537.  
  4538.         ckstrncpy(szUserNameAuthenticated,name,128);
  4539.     if (szUserNameRequested[0] &&
  4540.         krb5_kuserok(k5_context, k5_ticket->enc_part2->client,
  4541.              szUserNameRequested))
  4542.         auth_finished(AUTH_VALID);
  4543.     else
  4544.         auth_finished(AUTH_USER);
  4545.  
  4546.         if (name)
  4547.             free(name);
  4548.         krb5_auth_con_getremotesubkey(k5_context, auth_context,
  4549.                                        &newkey);
  4550.         if (k5_session_key) {
  4551.             krb5_free_keyblock(k5_context, k5_session_key);
  4552.             k5_session_key = 0;
  4553.         }
  4554.         if (newkey) {
  4555.             krb5_copy_keyblock(k5_context, newkey, &k5_session_key);
  4556.             krb5_free_keyblock(k5_context, newkey);
  4557.         } else {
  4558.             krb5_copy_keyblock(k5_context,
  4559.                                  k5_ticket->enc_part2->session,
  4560.                                 &k5_session_key);
  4561.         }
  4562.  
  4563. #ifdef CK_ENCRYPTION
  4564.         skey.type = k5_session_key->length == 8 ? SK_DES : SK_GENERIC;
  4565.         skey.length = k5_session_key->length;
  4566.         skey.data = k5_session_key->contents;
  4567.         encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  4568. #endif
  4569.         debug(F100,"k5_auth_is AUTH_SUCCESS","",0);
  4570.         krb5_errno = r;
  4571.         if ( krb5_errno )
  4572.             makestr(&krb5_errmsg,error_message(krb5_errno));
  4573.         else
  4574.             makestr(&krb5_errmsg,strTmp);
  4575.         return AUTH_SUCCESS;
  4576.  
  4577. #ifdef FORWARD
  4578.     case KRB5_FORWARD:
  4579.     if ( !forward_flag ) {
  4580.             SendK5AuthSB(KRB5_FORWARD_REJECT,
  4581.               "forwarded credentials are being refused.",
  4582.               -1);
  4583.         return(AUTH_SUCCESS);
  4584.     }
  4585.  
  4586.         inbuf.length = cnt;
  4587.         inbuf.data = (char *)data;
  4588.         if ((r = krb5_auth_con_genaddrs(k5_context,auth_context,g_kstream->fd,
  4589.                   KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR)) ||
  4590.         (r = rd_and_store_for_creds(k5_context, auth_context,
  4591.                   &inbuf, k5_ticket, szUserNameRequested))) {
  4592.             (void) strcpy(errbuf, "Read forwarded creds failed: ");
  4593.             (void) strcat(errbuf, error_message(r));
  4594.             SendK5AuthSB(KRB5_FORWARD_REJECT, errbuf, -1);
  4595.             printf("Could not read forwarded credentials\r\n");
  4596.             krb5_errno = r;
  4597.             makestr(&krb5_errmsg,error_message(krb5_errno));
  4598.         }
  4599.         else {
  4600.             SendK5AuthSB(KRB5_FORWARD_ACCEPT, 0, 0);
  4601.             sprintf(strTmp,"Forwarded credentials obtained");
  4602.             printf("%s\r\n",strTmp);
  4603.             krb5_errno = r;
  4604.             makestr(&krb5_errmsg,strTmp);
  4605.         }
  4606.     /* A failure to accept forwarded credentials is not an */
  4607.     /* authentication failure.                             */
  4608.     return AUTH_SUCCESS;
  4609. #endif    /* FORWARD */
  4610.     default:
  4611.         printf("Unknown Kerberos option %d\r\n", data[-1]);
  4612.         SendK5AuthSB(KRB_REJECT, 0, 0);
  4613.         break;
  4614.     }
  4615.     auth_finished(AUTH_REJECT);
  4616.     return AUTH_FAILURE;
  4617.  
  4618.   errout:
  4619.     SendK5AuthSB(KRB_REJECT, errbuf, -1);
  4620.     krb5_errno = r;
  4621.     makestr(&krb5_errmsg,errbuf);
  4622.     printf("%s\r\n", errbuf);
  4623.     if (auth_context) {
  4624.         krb5_auth_con_free(k5_context, auth_context);
  4625.         auth_context = 0;
  4626.     }
  4627.     auth_finished(AUTH_REJECT);
  4628.     return AUTH_FAILURE;
  4629. }
  4630.  
  4631. #ifdef FORWARD
  4632. VOID
  4633. #ifdef CK_ANSIC
  4634. kerberos5_forward(void)
  4635. #else
  4636. kerberos5_forward()
  4637. #endif
  4638. {
  4639.     krb5_error_code r;
  4640.     krb5_ccache ccache=NULL;
  4641.     krb5_principal client = 0;
  4642.     krb5_principal server = 0;
  4643.     krb5_data forw_creds;
  4644.  
  4645.     forw_creds.data = 0;
  4646.  
  4647.     r = k5_get_ccache(k5_context,&ccache,NULL);
  4648.     if ( r ) {
  4649.         com_err(NULL, r, "Kerberos V5: could not get default ccache");
  4650.         krb5_errno = r;
  4651.         makestr(&krb5_errmsg,error_message(krb5_errno));
  4652.         return;
  4653.     }
  4654.  
  4655.     if ((r = krb5_cc_get_principal(k5_context, ccache, &client))) {
  4656.         com_err(NULL, r, "Kerberos V5: could not get default principal");
  4657.         goto cleanup;
  4658.     }
  4659.  
  4660.     if ((r = krb5_sname_to_principal(k5_context, szHostName,
  4661.                                krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME,
  4662.                      KRB5_NT_SRV_HST, &server))) {
  4663.         com_err(NULL, r, "Kerberos V5: could not make server principal");
  4664.         goto cleanup;
  4665.     }
  4666.  
  4667.     if ((r = krb5_auth_con_genaddrs(k5_context, auth_context, g_kstream->fd,
  4668.                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR))) {
  4669.         com_err(NULL, r, "Kerberos V5: could not gen local full address");
  4670.         goto cleanup;
  4671.     }
  4672.  
  4673.     if (r = krb5_fwd_tgt_creds(k5_context, auth_context, 0, client, server,
  4674.                     ccache, forwardable_flag, &forw_creds)) {
  4675.         com_err(NULL, r, "Kerberos V5: error getting forwardable credentials");
  4676.         goto cleanup;
  4677.     }
  4678.  
  4679.     /* Send forwarded credentials */
  4680.     if (!SendK5AuthSB(KRB5_FORWARD, forw_creds.data, forw_creds.length)) {
  4681.         printf("Kerberos V5 forwarding error!\r\n%s\r\n",
  4682.                     "Not enough room for authentication data");
  4683.     }
  4684.  
  4685. cleanup:
  4686.     if (client)
  4687.         krb5_free_principal(k5_context, client);
  4688.     if (server)
  4689.         krb5_free_principal(k5_context, server);
  4690. #if 0 /* XXX */
  4691.     if (forw_creds.data)
  4692.         free(forw_creds.data);
  4693. #endif
  4694.     krb5_cc_close(k5_context, ccache);
  4695.  
  4696.     krb5_errno = r;
  4697.     makestr(&krb5_errmsg,error_message(krb5_errno));
  4698. }
  4699. #endif /* FORWARD */
  4700. #else /* KRB5 */
  4701. int
  4702. ck_krb5_autoget_TGT(char * dummy)
  4703. {
  4704.     return(0);
  4705. }
  4706. #ifdef CK_KERBEROS
  4707. int
  4708. #ifdef CK_ANSIC
  4709. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init )
  4710. #else
  4711. ck_krb5_initTGT(op,init)
  4712.     krb_op_data * op; struct krb5_init_data * init;
  4713. #endif /* CK_ANSIC*/
  4714. {
  4715.     return(-1);
  4716. }
  4717.  
  4718. int
  4719. #ifdef CK_ANSIC
  4720. ck_krb5_destroy(struct krb_op_data * op)
  4721. #else
  4722. ck_krb5_destroy(op) struct krb_op_data * op;
  4723. #endif
  4724. {
  4725.     return(-1);
  4726. }
  4727.  
  4728. int
  4729. #ifdef CK_ANSIC
  4730. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  4731. #else
  4732. ck_krb5_list_creds(op,lc)
  4733.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  4734. #endif
  4735. {
  4736.     return(-1);
  4737. }
  4738. #else /* CK_KERBEROS */
  4739. int
  4740. #ifdef CK_ANSIC
  4741. ck_krb5_initTGT(void * op, void * init )
  4742. #else
  4743. ck_krb5_initTGT(op,init)
  4744.     void * op; void * init;
  4745. #endif /* CK_ANSIC*/
  4746. {
  4747.     return(-1);
  4748. }
  4749.  
  4750. int
  4751. #ifdef CK_ANSIC
  4752. ck_krb5_destroy(void * op)
  4753. #else
  4754. ck_krb5_destroy(op) void * op;
  4755. #endif
  4756. {
  4757.     return(-1);
  4758. }
  4759.  
  4760. int
  4761. #ifdef CK_ANSIC
  4762. ck_krb5_list_creds(void * op, void * lc)
  4763. #else
  4764. ck_krb5_list_creds(op,lc)
  4765.     void * op; void * lc;
  4766. #endif
  4767. {
  4768.     return(-1);
  4769. }
  4770. #endif /* CK_KERBEROS */
  4771. #endif /* KRB5 */
  4772.  
  4773. #ifdef CK_SRP
  4774. /*
  4775.  * Copyright (c) 1997 Stanford University
  4776.  *
  4777.  * The use of this software for revenue-generating purposes may require a
  4778.  * license from the owners of the underlying intellectual property.
  4779.  * Specifically, the SRP-3 protocol may not be used for revenue-generating
  4780.  * purposes without a license.
  4781.  *
  4782.  * Within that constraint, permission to use, copy, modify, and distribute
  4783.  * this software and its documentation for any purpose is hereby granted
  4784.  * without fee, provided that the above copyright notices and this permission
  4785.  * notice appear in all copies of the software and related documentation.
  4786.  *
  4787.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  4788.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  4789.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  4790.  *
  4791.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  4792.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
  4793.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
  4794.  * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
  4795.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  4796.  */
  4797.  
  4798.  
  4799. static void
  4800. srp_encode_length(data, num)
  4801.     unsigned char * data;
  4802.     int num;
  4803. {
  4804.     *data = (num >> 8) & 0xff;
  4805.     *++data = num & 0xff;
  4806. }
  4807.  
  4808. static int
  4809. srp_decode_length(data)
  4810.     unsigned char * data;
  4811. {
  4812.     return (((int) *data & 0xff) << 8) | (*(data + 1) & 0xff);
  4813. }
  4814.  
  4815.  
  4816. static int
  4817. #ifdef CK_ANSIC
  4818. srp_reply(int how, unsigned char *data, int cnt)
  4819. #else
  4820. srp_reply(how,data,cnt) int how; unsigned char *data; int cnt;
  4821. #endif
  4822. {
  4823.     struct t_num n;
  4824.     struct t_num g;
  4825.     struct t_num s;
  4826.  
  4827.     struct t_num B;
  4828.     struct t_num * A;
  4829.  
  4830.     char hexbuf[MAXHEXPARAMLEN];
  4831.     char type_check[2];
  4832.     int pflag;
  4833.  
  4834. #ifdef CK_ENCRYPTION
  4835.     Session_Key skey;
  4836. #endif /* ENCRYPTION */
  4837.  
  4838.     char * str=NULL;
  4839.  
  4840.     data += 4;                          /* Point to status byte */
  4841.     cnt  -= 4;
  4842.  
  4843.     if(cnt-- < 1) {
  4844.         auth_finished(AUTH_REJECT);
  4845.         return AUTH_FAILURE;
  4846.     }
  4847.  
  4848.     switch(*data++) {
  4849.     case SRP_REJECT:
  4850.         if (cnt > 0) {
  4851.             sprintf(strTmp,
  4852.                      "SRP refuses authentication for '%s' (%.*s)\r\n",
  4853.                      szUserName, cnt, data);
  4854.             str = strTmp + strlen(strTmp);
  4855.             memcpy(str,data,cnt);
  4856.             str[cnt] = 0;
  4857.         } else
  4858.             sprintf(strTmp,"SRP refuses authentication for '%s'\r\n",
  4859.                      szUserName);
  4860.         printf("SRP authentication failed!\r\n%s\r\n",strTmp);
  4861.         auth_finished(AUTH_REJECT);
  4862.         return AUTH_FAILURE;
  4863.  
  4864.     case SRP_ACCEPT:
  4865.         if(tc == NULL || cnt < RESPONSE_LEN || !srp_waitresp) {
  4866.             printf("SRP Protocol error\r\n");
  4867.             auth_finished(AUTH_REJECT);
  4868.             return AUTH_FAILURE;
  4869.         }
  4870.         srp_waitresp = 0;
  4871.  
  4872.         if(t_clientverify(tc, data) == 0) {
  4873.             printf("SRP accepts you as %s\r\n",szUserName);
  4874.  
  4875. #ifdef CK_ENCRYPTION
  4876.             skey.type = SK_GENERIC;
  4877.             skey.length = SESSION_KEY_LEN;
  4878.             skey.data = tc->session_key;
  4879.             encrypt_session_key(&skey, AUTH_CLIENT_TO_SERVER);
  4880. #endif /* ENCRYPTION */
  4881.             accept_complete = 1;
  4882.             auth_finished(AUTH_VALID);
  4883.             return AUTH_SUCCESS;
  4884.         }
  4885.         else {
  4886.             printf("SRP server authentication failed!\r\n");
  4887.             auth_finished(AUTH_REJECT);
  4888.             return AUTH_FAILURE;
  4889.         }
  4890.         break;
  4891.  
  4892.     case SRP_PARAMS:
  4893.         if(!szUserName) {
  4894.             printf("No username available\r\n");
  4895.             auth_finished(AUTH_REJECT);
  4896.             return AUTH_FAILURE;
  4897.         }
  4898.  
  4899.         n.len = srp_decode_length(data);
  4900.         data += 2;
  4901.         cnt -= 2;
  4902.         if(n.len > cnt) {
  4903.             printf("n too long\r\n");
  4904.             auth_finished(AUTH_REJECT);
  4905.             return AUTH_FAILURE;
  4906.         }
  4907.         n.data = data;
  4908.         data += n.len;
  4909.         cnt -= n.len;
  4910.  
  4911.         g.len = srp_decode_length(data);
  4912.         data += 2;
  4913.         cnt -= 2;
  4914.         if(g.len > cnt) {
  4915.             printf("g too long\r\n");
  4916.             auth_finished(AUTH_REJECT);
  4917.             return AUTH_FAILURE;
  4918.         }
  4919.         g.data = data;
  4920.         data += g.len;
  4921.         cnt -= g.len;
  4922.  
  4923.         s.len = srp_decode_length(data);
  4924.         data += 2;
  4925.         cnt -= 2;
  4926.         if(s.len > cnt) {
  4927.             printf("salt too long\r\n");
  4928.             auth_finished(AUTH_REJECT);
  4929.             return AUTH_FAILURE;
  4930.         }
  4931.         s.data = data;
  4932.         data += s.len;
  4933.         cnt -= s.len;
  4934.  
  4935.         tc = t_clientopen(szUserName, &n, &g, &s);
  4936.  
  4937.         A = t_clientgenexp(tc);
  4938.  
  4939.         SendSRPAuthSB(SRP_EXP, A->data, A->len);
  4940.  
  4941.         if ( pwbuf[0] && pwflg ) {
  4942.             printf("SRP using %d-bit modulus for '%s'\r\n",
  4943.            8 * n.len,
  4944.            szUserName
  4945.            );
  4946.             ckstrncpy(srp_passwd,pwbuf,sizeof(srp_passwd));
  4947. #ifdef OS2
  4948.             if ( pwcrypt )
  4949.                 ck_encrypt((char *)srp_passwd);
  4950. #endif /* OS2 */
  4951.         } else {
  4952.             extern char * srppwprompt;
  4953.             char prompt[128];
  4954.             sprintf(prompt,"SRP using %d-bit modulus\r\n%s's password: ",
  4955.                      8 * n.len,szUserName);
  4956.             readpass(srppwprompt && srppwprompt[0] ? srppwprompt :
  4957.                       prompt,srp_passwd,sizeof(srp_passwd)-1);
  4958.         }
  4959.  
  4960.         t_clientpasswd(tc, srp_passwd);
  4961.         memset(srp_passwd, 0, sizeof(srp_passwd));
  4962.         return AUTH_SUCCESS;
  4963.  
  4964.     case SRP_CHALLENGE:
  4965.         if(tc == NULL) {
  4966.             printf("Protocol error\r\n");
  4967.             auth_finished(AUTH_REJECT);
  4968.             return AUTH_FAILURE;
  4969.         }
  4970.  
  4971. #ifndef PRE_SRP_1_4_5
  4972.         if ( (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT ) {
  4973.             type_check[0] = AUTHTYPE_SRP;
  4974.             type_check[1] = how;
  4975.             t_clientaddexdata(tc,type_check,2);
  4976.         }
  4977. #endif /* PRE_SRP_1_4_5 */
  4978.  
  4979.         B.data = data;
  4980.         B.len = cnt;
  4981.         t_clientgetkey(tc, &B);
  4982.  
  4983.         SendSRPAuthSB(SRP_RESPONSE, t_clientresponse(tc), RESPONSE_LEN);
  4984.         srp_waitresp = 1;
  4985.         return AUTH_SUCCESS;
  4986.  
  4987.     default:
  4988.         auth_finished(AUTH_REJECT);
  4989.         return AUTH_FAILURE;
  4990.     }
  4991.     return AUTH_FAILURE;
  4992. }
  4993.  
  4994. static int
  4995. #ifdef CK_ANSIC
  4996. srp_is(int how, unsigned char *data, int cnt)
  4997. #else
  4998. srp_is(how,data,cnt) int how; unsigned char *data; int cnt;
  4999. #endif
  5000. {
  5001.     char pbuf[2 * MAXPARAMLEN + 5];
  5002.     char * ptr;
  5003.     struct t_num A;
  5004.     char hexbuf[MAXHEXPARAMLEN];
  5005.     struct passwd * pass;
  5006. #ifdef CK_ENCRYPTION
  5007.     Session_Key skey;
  5008. #endif
  5009.     struct t_pw * tpw = NULL;
  5010.     struct t_conf * tconf = NULL;
  5011.     char type_check[2];
  5012.  
  5013.     if ((cnt -= 4) < 1) {
  5014.         auth_finished(AUTH_REJECT);
  5015.         return AUTH_FAILURE;
  5016.     }
  5017.  
  5018.     data += 4;
  5019.     cnt  -= 1;
  5020.     switch(*data++) {
  5021.     case SRP_AUTH:
  5022.         /* Send parameters back to client */
  5023.         if(ts != NULL) {
  5024.             t_serverclose(ts);
  5025.             ts = NULL;
  5026.         }
  5027.         if(!szUserNameRequested[0]) {
  5028.             if (1)
  5029.                 printf("No username available\r\n");
  5030.             SendSRPAuthSB(SRP_REJECT, (void *) "No username supplied", -1);
  5031.             auth_finished(AUTH_REJECT);
  5032.             return(AUTH_FAILURE);
  5033.         }
  5034. #ifdef IKSD
  5035. #ifdef CK_LOGIN
  5036.         if (inserver && ckxanon &&
  5037.              !strcmp(szUserNameRequested,"anonymous")) {
  5038.             SendSRPAuthSB(SRP_REJECT, (void *)
  5039.             "anonymous login cannot be performed with Secure Remote Password",
  5040.             -1);
  5041.             auth_finished(AUTH_REJECT);
  5042.             return(AUTH_FAILURE);
  5043.         }
  5044. #endif /* CK_LOGIN */
  5045. #endif /* IKSD */
  5046. #ifdef PRE_SRP_1_4_4
  5047.         if(tpw == NULL) {
  5048.             if((tpw = t_openpw(NULL)) == NULL) {
  5049.                 if (1)
  5050.                     printf("Unable to open password file\r\n");
  5051.                 SendSRPAuthSB(SRP_REJECT, (void *) "No password file", -1);
  5052.                 return(AUTH_FAILURE);
  5053.             }
  5054.         }
  5055.         if(tconf == NULL) {
  5056.             if((tconf = t_openconf(NULL)) == NULL) {
  5057.                 if (1)
  5058.           printf("Unable to open configuration file\r\n");
  5059.                 SendSRPAuthSB(SRP_REJECT, (void *)"No configuration file", -1);
  5060.                 return(AUTH_FAILURE);
  5061.             }
  5062.         }
  5063.         ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  5064.         t_closepw(tpw);
  5065.         tpw = NULL;
  5066.         t_closeconf(tconf);
  5067.         tconf = NULL;
  5068. #else /* PRE_SRP_1_4_4 */
  5069.         /* On Windows and OS/2 there is no well defined place for the */
  5070.         /* ETC directory.  So we look for either an SRP_ETC or ETC    */
  5071.         /* environment variable in that order.  If we find one we     */
  5072.         /* attempt to open the files manually.                        */
  5073.         /* We will reuse the pbuf[] for the file names. */
  5074.         ptr = getenv("SRP_ETC");
  5075.         if ( !ptr )
  5076.             ptr = getenv("ETC");
  5077.         if ( ptr ) {
  5078.             int len = strlen(ptr);
  5079.             int i;
  5080.             strcpy(pbuf,ptr);
  5081.             for ( i=0;i<len;i++ ) {
  5082.                 if ( pbuf[i] == '\\' )
  5083.                     pbuf[i] = '/';
  5084.             }
  5085.             if ( pbuf[len-1] != '/' )
  5086.                 strcat(pbuf,"/tpasswd");
  5087.             else
  5088.                 strcat(pbuf,"tpasswd");
  5089.             tpw = t_openpwbyname(pbuf);
  5090.  
  5091.             strcat(pbuf,".conf");
  5092.             tconf = t_openconfbyname(pbuf);
  5093.         }
  5094.  
  5095.         if ( tpw && tconf )
  5096.             ts = t_serveropenfromfiles(szUserNameRequested, tpw, tconf);
  5097.         else
  5098.             ts = t_serveropen(szUserNameRequested);
  5099.         if ( tpw ) {
  5100.             t_closepw(tpw);
  5101.             tpw = NULL;
  5102.         }
  5103.         if ( tconf ) {
  5104.             t_closeconf(tconf);
  5105.             tconf = NULL;
  5106.         }
  5107. #endif /* PRE_SRP_1_4_4 */
  5108.  
  5109.         if(ts == NULL) {
  5110.             if (1)
  5111.                 printf("User %s not found\r\n", szUserNameRequested);
  5112.             SendSRPAuthSB(SRP_REJECT, (void *) "Password not set", -1);
  5113.             return(AUTH_FAILURE);
  5114.         }
  5115.         ptr = pbuf;
  5116.  
  5117.         srp_encode_length(ptr, ts->n.len);
  5118.         ptr += 2;
  5119.         memcpy(ptr, ts->n.data, ts->n.len);
  5120.         ptr += ts->n.len;
  5121.  
  5122.         srp_encode_length(ptr, ts->g.len);
  5123.         ptr += 2;
  5124.         memcpy(ptr, ts->g.data, ts->g.len);
  5125.         ptr += ts->g.len;
  5126.  
  5127.         srp_encode_length(ptr, ts->s.len);
  5128.         ptr += 2;
  5129.         memcpy(ptr, ts->s.data, ts->s.len);
  5130.         ptr += ts->s.len;
  5131.  
  5132.         SendSRPAuthSB(SRP_PARAMS, pbuf, ptr - pbuf);
  5133.  
  5134.         B = t_servergenexp(ts);
  5135.         ckstrncpy(szUserNameAuthenticated,szUserNameRequested,128);
  5136.         return AUTH_SUCCESS;
  5137.  
  5138.     case SRP_EXP:
  5139.         /* Client is sending A to us, compute challenge & expected response. */
  5140.         if (ts == NULL || B == NULL) {
  5141.             if (1)
  5142.           printf("Protocol error: SRP_EXP unexpected\r\n");
  5143.             SendSRPAuthSB(SRP_REJECT,
  5144.               (void *) "Protocol error: unexpected EXP",
  5145.               -1
  5146.               );
  5147.             return(AUTH_FAILURE);
  5148.         }
  5149.  
  5150.         /* Wait until now to send B, since it contains the key to "u" */
  5151.         SendSRPAuthSB(SRP_CHALLENGE, B->data, B->len);
  5152.         B = NULL;
  5153.  
  5154. #ifndef PRE_SRP_1_4_5
  5155.         if ( (how & AUTH_ENCRYPT_MASK) == AUTH_ENCRYPT_USING_TELOPT ) {
  5156.             type_check[0] = AUTHTYPE_SRP;
  5157.             type_check[1] = how;
  5158.             t_serveraddexdata(ts,type_check,2);
  5159.         }
  5160. #endif /* PRE_SRP_1_4_5 */
  5161.         A.data = data;
  5162.         A.len = cnt;
  5163.         ptr = t_servergetkey(ts, &A);
  5164.  
  5165.         if(ptr == NULL) {
  5166.             if (1)
  5167.           printf("Security alert: Trivial session key attempted\r\n");
  5168.             SendSRPAuthSB(SRP_REJECT,
  5169.               (void *) "Trivial session key detected",
  5170.               -1
  5171.               );
  5172.             return(AUTH_FAILURE);
  5173.         }
  5174.         srp_waitresp = 1;
  5175.         return AUTH_SUCCESS;
  5176.  
  5177.     case SRP_RESPONSE:
  5178.         /* Got the response; see if it's correct */
  5179.         if(ts == NULL || !srp_waitresp) {
  5180.             if (1)
  5181.           printf("Protocol error: SRP_RESPONSE unexpected\r\n");
  5182.             SendSRPAuthSB(SRP_REJECT,
  5183.               (void *) "Protocol error: unexpected RESPONSE",
  5184.               -1
  5185.               );
  5186.             return(AUTH_FAILURE);
  5187.         }
  5188.     srp_waitresp = 0;    /* we got a response */
  5189.  
  5190.         if (cnt < RESPONSE_LEN) {
  5191.             if (1)
  5192.           printf("Protocol error: malformed response\r\n");
  5193.             SendSRPAuthSB(SRP_REJECT,
  5194.               (void *) "Protocol error: malformed response",
  5195.               -1
  5196.               );
  5197.             return(AUTH_FAILURE);
  5198.         }
  5199.         if (t_serververify(ts, data) == 0) {
  5200.             SendSRPAuthSB(SRP_ACCEPT, t_serverresponse(ts), RESPONSE_LEN);
  5201.             accept_complete = 1;
  5202. #ifdef CK_ENCRYPTION
  5203.             hexdump("SRP_RESPONSE ts",ts,sizeof(ts));
  5204.             hexdump("SRP_RESPONSE session_key",
  5205.             ts->session_key,
  5206.             SESSION_KEY_LEN
  5207.             );
  5208.             skey.type = SK_GENERIC;
  5209.             skey.length = SESSION_KEY_LEN;
  5210.             skey.data = ts->session_key;
  5211.             encrypt_session_key(&skey, AUTH_SERVER_TO_CLIENT);
  5212. #endif
  5213.             auth_finished(AUTH_VALID);
  5214.         }
  5215.         else {
  5216.             SendSRPAuthSB(SRP_REJECT, (void *) "Login incorrect", -1);
  5217.             auth_finished(AUTH_REJECT);
  5218.             return(AUTH_FAILURE);
  5219.         }
  5220.         return AUTH_SUCCESS;
  5221.  
  5222.     default:
  5223.         if (1)
  5224.             printf("Unknown SRP option %d\r\n", data[-1]);
  5225.         SendSRPAuthSB(SRP_REJECT, (void *) "Unknown option received", -1);
  5226.         return(AUTH_FAILURE);
  5227.     }
  5228. }
  5229. #endif /* SRP */
  5230.  
  5231. #ifdef KRB5
  5232. #ifdef KINIT
  5233. /*
  5234.  * clients/kinit/kinit.c
  5235.  *
  5236.  * Copyright 1990 by the Massachusetts Institute of Technology.
  5237.  * All Rights Reserved.
  5238.  *
  5239.  * Export of this software from the United States of America may
  5240.  *   require a specific license from the United States Government.
  5241.  *   It is the responsibility of any person or organization contemplating
  5242.  *   export to obtain such a license before exporting.
  5243.  *
  5244.  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  5245.  * distribute this software and its documentation for any purpose and
  5246.  * without fee is hereby granted, provided that the above copyright
  5247.  * notice appear in all copies and that both that copyright notice and
  5248.  * this permission notice appear in supporting documentation, and that
  5249.  * the name of M.I.T. not be used in advertising or publicity pertaining
  5250.  * to distribution of the software without specific, written prior
  5251.  * permission.  M.I.T. makes no representations about the suitability of
  5252.  * this software for any purpose.  It is provided "as is" without express
  5253.  * or implied warranty.
  5254.  *
  5255.  *
  5256.  * Initialize a credentials cache.
  5257.  */
  5258.  
  5259. #define KRB5_DEFAULT_OPTIONS 0
  5260. #define KRB5_DEFAULT_LIFE 60*60*10 /* 10 hours */
  5261.  
  5262. static krb5_data tgtname = {
  5263.     0,
  5264.     KRB5_TGS_NAME_SIZE,
  5265.     KRB5_TGS_NAME
  5266. };
  5267.  
  5268. /* Internal prototypes */
  5269. static krb5_error_code krb5_validate_tgt
  5270.         KRB5_PROTOTYPE((krb5_context, krb5_ccache,
  5271.                         krb5_principal, krb5_data *));
  5272. static krb5_error_code krb5_renew_tgt
  5273.         KRB5_PROTOTYPE((krb5_context, krb5_ccache,
  5274.                         krb5_principal, krb5_data *));
  5275. static krb5_error_code krb5_tgt_gen
  5276.         KRB5_PROTOTYPE((krb5_context, krb5_ccache,
  5277.                         krb5_principal, krb5_data *, int opt));
  5278.  
  5279. /*
  5280.  * Try no preauthentication first; then try the encrypted timestamp
  5281.  */
  5282. static krb5_preauthtype * preauth = NULL;
  5283. static krb5_preauthtype preauth_list[2] = { 0, -1 };
  5284.  
  5285. #define NO_KEYTAB
  5286.  
  5287. int
  5288. #ifdef CK_ANSIC
  5289. ck_krb5_initTGT( struct krb_op_data * op, struct krb5_init_data * init )
  5290. #else
  5291. ck_krb5_initTGT(op,init)
  5292.     krb_op_data * op; struct krb5_init_data * init;
  5293. #endif /* CK_ANSIC*/
  5294. {
  5295.     krb5_context kcontext;
  5296.     krb5_ccache ccache = NULL;
  5297.     krb5_deltat lifetime = KRB5_DEFAULT_LIFE;    /* -l option */
  5298.     krb5_timestamp starttime = 0;
  5299.     krb5_deltat rlife = 0;
  5300.     int options = KRB5_DEFAULT_OPTIONS;
  5301.     int option;
  5302.     int errflg = 0;
  5303.     krb5_error_code code;
  5304.     krb5_principal me=NULL;
  5305.     krb5_principal server=NULL;
  5306.     krb5_creds my_creds;
  5307.     krb5_timestamp now;
  5308.     krb5_address **addrs = (krb5_address **)0;
  5309.     int addr_count=0;
  5310.     int i,j;
  5311. #ifndef NO_KEYTAB
  5312.     int use_keytab = 0;            /* -k option */
  5313.     krb5_keytab keytab = NULL;
  5314. #endif /* NO_KEYTAB */
  5315.     struct passwd *pw = 0;
  5316.     int pwsize;
  5317.     char *client_name=NULL, realm[256]="", numstr[40]="";
  5318.  
  5319.     if ( !ck_krb5_is_installed() )
  5320.         return(-1);
  5321.  
  5322. #ifdef COMMENT
  5323.     printf("Kerberos V initialization\r\n");
  5324. #endif /* COMMENT */
  5325.  
  5326.     code = krb5_init_context(&kcontext);
  5327.     if (code) {
  5328.         com_err("krb5_kinit",code,"while init_context");
  5329.         krb5_errno = code;
  5330.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5331.         return(-1);
  5332.     }
  5333.  
  5334.     if ((code = krb5_timeofday(kcontext, &now))) {
  5335.         com_err("krb5_kinit",code,"while getting time of day");
  5336.         goto exit_k5_init;
  5337.     }
  5338.  
  5339.     if ( init->renewable ) {
  5340.         options |= KDC_OPT_RENEWABLE;
  5341.         sprintf(numstr,"%dm",init->renewable);
  5342.         code = krb5_string_to_deltat(numstr, &rlife);
  5343.         if (code != 0 || rlife == 0) {
  5344.             printf("Bad renewable time value %s\r\n", numstr);
  5345.             errflg++;
  5346.         }
  5347.     }
  5348.     if ( init->renew ) {
  5349.         /* renew the ticket */
  5350.         options |= KDC_OPT_RENEW;
  5351.     }
  5352.  
  5353.     if ( init->validate ) {
  5354.         /* validate the ticket */
  5355.         options |= KDC_OPT_VALIDATE;
  5356.     }
  5357.     if ( init->proxiable ) {
  5358.         options |= KDC_OPT_PROXIABLE;
  5359.     }
  5360.     if ( init->forwardable ) {
  5361.         options |= KDC_OPT_FORWARDABLE;
  5362.     }
  5363. #ifndef NO_KEYTAB
  5364.     if (  ) {
  5365.         use_keytab = 1;
  5366.     }
  5367.     if (  ) {
  5368.         if (keytab == NULL && keytab_name != NULL) {
  5369.             code = krb5_kt_resolve(kcontext, keytab_name, &keytab);
  5370.             if (code != 0) {
  5371.                 debug(F111,"krb5_init resolving keytab",
  5372.                          keytab_name,code);
  5373.                 errflg++;
  5374.             }
  5375.         }
  5376.     }
  5377. #endif
  5378.     if ( init->lifetime ) {
  5379.         sprintf(numstr,"%dm",init->lifetime);
  5380.         code = krb5_string_to_deltat(numstr, &lifetime);
  5381.         if (code != 0 || lifetime == 0) {
  5382.             printf("Bad lifetime value %s\r\n", numstr);
  5383.             errflg++;
  5384.         }
  5385.     }
  5386.     if ( init->postdate ) {
  5387.         /* Convert cmdate() to a time_t value */
  5388.         struct tm * time_tm;
  5389.         struct tm * cmdate2tm(char *,int);
  5390.         time_tm = cmdate2tm(init->postdate,0);
  5391.         if ( time_tm )
  5392.             starttime = (krb5_timestamp) mktime(time_tm);
  5393.  
  5394.         if (code != 0 || starttime == 0 || starttime == -1) {
  5395.             krb5_deltat ktmp;
  5396.             code = krb5_string_to_deltat(init->postdate, &ktmp);
  5397.             if (code == 0 && ktmp != 0) {
  5398.         starttime = now + ktmp;
  5399.         options |= KDC_OPT_POSTDATED;
  5400.             } else {
  5401.         printf("Bad postdate start time value %s\r\n",
  5402.                         init->postdate);
  5403.         errflg++;
  5404.             }
  5405.         } else {
  5406.             options |= KDC_OPT_POSTDATED;
  5407.         }
  5408.     }
  5409.  
  5410.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  5411.     if (code != 0) {
  5412.         com_err("krb5_kinit",code,"while getting default ccache");
  5413.         goto exit_k5_init;
  5414.     }
  5415.  
  5416.     if (init->principal == NULL) {       /* No principal name specified */
  5417. #ifndef NO_KEYTAB
  5418.         if (use_keytab) {
  5419.             /* Use the default host/service name */
  5420.             code = krb5_sname_to_principal(kcontext, NULL, NULL,
  5421.                                             KRB5_NT_SRV_HST, &me);
  5422.             if (code) {
  5423.                 com_err("krb5_kinit",
  5424.             code,
  5425.             "when creating default server principal name");
  5426.                 goto exit_k5_init;
  5427.             }
  5428.         } else
  5429. #endif
  5430.         {
  5431.             /* Get default principal from cache if one exists */
  5432.             code = krb5_cc_get_principal(kcontext, ccache, &me);
  5433.             if (code) {
  5434. #ifdef HAVE_PWD_H
  5435.                 /* Else search passwd file for client */
  5436.                 pw = getpwuid((int) getuid());
  5437.                 if (pw) {
  5438.                     if ((code = krb5_parse_name(kcontext,pw->pw_name,
  5439.                                                  &me))) {
  5440.                         krb5_errno = code;
  5441.                         com_err("krb5_kinit",code,"when parsing name",
  5442.                                   pw->pw_name);
  5443.                         goto exit_k5_init;
  5444.                     }
  5445.                 } else {
  5446.                     printf(
  5447.                         "Unable to identify user from password file\r\n");
  5448.                     goto exit_k5_init;
  5449.                 }
  5450. #else /* HAVE_PWD_H */
  5451.                 printf("Unable to identify user\r\n");
  5452.                 goto exit_k5_init;
  5453. #endif /* HAVE_PWD_H */
  5454.             }
  5455.         }
  5456.     } /* Use specified name */
  5457.     else {
  5458.         char princ_realm[256];
  5459.         if ( (strlen(init->principal) +
  5460.           (init->instance ? strlen(init->instance)+1 : 0) +
  5461.           strlen(init->realm ? init->realm : krb5_d_realm)
  5462.           + 2) > 255 )
  5463.              goto exit_k5_init;
  5464.  
  5465.         strcpy(princ_realm,init->principal);
  5466.         if (init->instance) {
  5467.             strcat(princ_realm,"/");
  5468.             strcat(princ_realm,init->instance);
  5469.         }
  5470.         strcat(princ_realm,"@");
  5471.         if ( init->realm )
  5472.             strcat(princ_realm,init->realm);
  5473.         else
  5474.             strcat(princ_realm,krb5_d_realm);
  5475.  
  5476.         if ((code = krb5_parse_name (kcontext, princ_realm, &me))) {
  5477.             com_err("krb5_kinit",code,"when parsing name",
  5478.                      princ_realm);
  5479.             goto exit_k5_init;
  5480.         }
  5481.     }
  5482.  
  5483.     if ( init->realm == NULL ) {
  5484.         /* Save the realm */
  5485.         memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  5486.                 krb5_princ_realm(kcontext, me)->length);
  5487.         realm[krb5_princ_realm(kcontext, me)->length]='\0';
  5488.     } else {
  5489.         strcpy(realm,init->realm);
  5490.     }
  5491.  
  5492.     if ((code = krb5_unparse_name(kcontext, me, &client_name))) {
  5493.     com_err("krb5_kinit",code,"when unparsing name");
  5494.         goto exit_k5_init;
  5495.     }
  5496.     memset((char *)&my_creds, 0, sizeof(my_creds));
  5497.  
  5498.     my_creds.client = me;
  5499.  
  5500.     if (init->service == NULL) {
  5501.         if ((code =
  5502.          krb5_build_principal_ext(kcontext,
  5503.                       &server,
  5504.                       strlen(realm),realm,
  5505.                       tgtname.length, tgtname.data,
  5506.                       strlen(realm),realm,
  5507.                       0))) {
  5508.             com_err("krb5_kinit",code,"while building server name");
  5509.             goto exit_k5_init;
  5510.         }
  5511.     } else {
  5512.         if (code = krb5_parse_name(kcontext, init->service, &server)) {
  5513.             com_err("krb5_kinit",code,"while parsing service name",
  5514.             init->service);
  5515.             goto exit_k5_init;
  5516.         }
  5517.     }
  5518.  
  5519.     my_creds.server = server;
  5520.  
  5521.     if (options & KDC_OPT_POSTDATED) {
  5522.         my_creds.times.starttime = starttime;
  5523.         my_creds.times.endtime = starttime + lifetime;
  5524.     } else {
  5525.         my_creds.times.starttime = 0;    /* start timer when request
  5526.                        gets to KDC */
  5527.         my_creds.times.endtime = now + lifetime;
  5528.     }
  5529.     if (options & KDC_OPT_RENEWABLE) {
  5530.     my_creds.times.renew_till = now + rlife;
  5531.     } else
  5532.     my_creds.times.renew_till = 0;
  5533.  
  5534.     if (options & KDC_OPT_VALIDATE) {
  5535.         /* don't use get_in_tkt, just use mk_req... */
  5536.         krb5_data outbuf;
  5537.  
  5538.         code = krb5_validate_tgt(kcontext, ccache, server, &outbuf);
  5539.     if (code) {
  5540.             com_err("krb5_kinit",code,"validating tgt");
  5541.             goto exit_k5_init;
  5542.     }
  5543.     /* should be done... */
  5544.         goto exit_k5_init;
  5545.     }
  5546.  
  5547.     if (options & KDC_OPT_RENEW) {
  5548.         /* don't use get_in_tkt, just use mk_req... */
  5549.         krb5_data outbuf;
  5550.  
  5551.         code = krb5_renew_tgt(kcontext, ccache, server, &outbuf);
  5552.     if (code) {
  5553.             com_err("krb5_kinit",code,"while renewing tgt");
  5554.             goto exit_k5_init;
  5555.     }
  5556.     /* should be done... */
  5557.         goto exit_k5_init;
  5558.     }
  5559.  
  5560.     if ( init->addrs ) {
  5561.         /* construct an array of krb5_address structs to pass to get_in_tkt */
  5562.         /* include both the local ip addresses as well as any other that    */
  5563.         /* are specified.                                                   */
  5564.         unsigned long ipaddr;
  5565.  
  5566.         for ( addr_count=0;addr_count<KRB5_NUM_OF_ADDRS;addr_count++ )
  5567.             if ( init->addrs[addr_count] == NULL )
  5568.                 break;
  5569.  
  5570.         if (addr_count > 0) {
  5571.             krb5_address ** local_addrs=NULL;
  5572.             krb5_os_localaddr(kcontext, &local_addrs);
  5573.             i = 0;
  5574.             while ( local_addrs[i] )
  5575.                 i++;
  5576.             addr_count += i;
  5577.  
  5578.             addrs = (krb5_address **)
  5579.           malloc((addr_count+1) * sizeof(krb5_address));
  5580.             if ( !addrs ) {
  5581.                 krb5_free_addresses(kcontext, local_addrs);
  5582.                 goto exit_k5_init;
  5583.             }
  5584.             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
  5585.             i = 0;
  5586.             while ( local_addrs[i] ) {
  5587.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  5588.                 if (addrs[i] == NULL) {
  5589.                     krb5_free_addresses(kcontext, local_addrs);
  5590.                     goto exit_k5_init;
  5591.                 }
  5592.  
  5593.                 addrs[i]->magic = local_addrs[i]->magic;
  5594.                 addrs[i]->addrtype = local_addrs[i]->addrtype;
  5595.                 addrs[i]->length = local_addrs[i]->length;
  5596.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  5597.                 if (!addrs[i]->contents) {
  5598.                     krb5_free_addresses(kcontext, local_addrs);
  5599.                     goto exit_k5_init;
  5600.                 }
  5601.  
  5602.                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
  5603.                         local_addrs[i]->length);
  5604.                 i++;
  5605.             }
  5606.             krb5_free_addresses(kcontext, local_addrs);
  5607.  
  5608.             for ( j=0;i<addr_count;i++,j++ ) {
  5609.                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
  5610.                 if (addrs[i] == NULL)
  5611.                     goto exit_k5_init;
  5612.  
  5613.                 addrs[i]->magic = KV5M_ADDRESS;
  5614.                 addrs[i]->addrtype = AF_INET;
  5615.                 addrs[i]->length = 4;
  5616.                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
  5617.                 if (!addrs[i]->contents)
  5618.                     goto exit_k5_init;
  5619.  
  5620.                 ipaddr = inet_addr(init->addrs[j]);
  5621.                 memcpy(addrs[i]->contents,&ipaddr,4);
  5622.             }
  5623.         }
  5624.      }
  5625.  
  5626. #ifndef NO_KEYTAB
  5627.     if (!use_keytab)
  5628. #endif
  5629.     {
  5630.         pwsize = strlen(init->password);
  5631.         if (pwsize == 0) {
  5632.             printf("A password must be specified for %s.\r\n",client_name);
  5633.             memset(init->password, 0, pwsize);
  5634.             goto exit_k5_init;
  5635.         }
  5636.  
  5637.      code = krb5_get_in_tkt_with_password(kcontext, options, addrs,
  5638.                           NULL, preauth, init->password,
  5639.                                                0, &my_creds, 0);
  5640.      memset(init->password, 0, pwsize);
  5641. #ifndef NO_KEYTAB
  5642.     } else {
  5643.         code = krb5_get_in_tkt_with_keytab(kcontext, options, addrs,
  5644.                         NULL, preauth, keytab, 0,
  5645.                         &my_creds, 0);
  5646. #endif
  5647.     }
  5648.  
  5649.     if (code) {
  5650.     switch (code) {
  5651.         case KRB5KRB_AP_ERR_BAD_INTEGRITY:
  5652.         printf("Password incorrect\r\n");
  5653.             goto exit_k5_init;
  5654.         case KRB5KRB_AP_ERR_V4_REPLY:
  5655.             if (init->getk4) {
  5656.                 printf("Kerberos 5 Tickets not support by server.  ");
  5657.                 printf("A version 4 Ticket will be requested.\r\n");
  5658.             }
  5659.             goto exit_k5_init;
  5660.         default:
  5661.             goto exit_k5_init;
  5662.         }
  5663.     }
  5664.  
  5665.     code = krb5_cc_initialize (kcontext, ccache, me);
  5666.     if (code != 0) {
  5667.     com_err("krb5_kinit",code,"when initializing cache",
  5668.          op->cache);
  5669.         goto exit_k5_init;
  5670.     }
  5671.  
  5672.     code = krb5_cc_store_cred(kcontext, ccache, &my_creds);
  5673.     if (code) {
  5674.     com_err("krb5_kinit",code,"while storing credentials");
  5675.         goto exit_k5_init;
  5676.     }
  5677.  
  5678. exit_k5_init:
  5679.  
  5680.     /* Free krb5_address structures if we created them */
  5681.     if ( addrs ) {
  5682.         for ( i=0;i<addr_count;i++ ) {
  5683.             if ( addrs[i] ) {
  5684.                 if ( addrs[i]->contents )
  5685.                     free(addrs[i]->contents);
  5686.                 free(addrs[i]);
  5687.             }
  5688.         }
  5689.     }
  5690.  
  5691.     /* my_creds is pointing at server */
  5692.     krb5_free_principal(kcontext, server);
  5693.     krb5_cc_close(kcontext,ccache);
  5694.     krb5_free_context(kcontext);
  5695.  
  5696.     krb5_errno = code;
  5697.     makestr(&krb5_errmsg,error_message(krb5_errno));
  5698.  
  5699.     if ( init->getk4 && code == KRB5KRB_AP_ERR_V4_REPLY )
  5700.         return(0);
  5701.  
  5702.     printf("Result from realm %s: %s\r\n",realm,
  5703.             code?error_message(code):"OK");
  5704.     return(code?-1:0);
  5705. }
  5706.  
  5707. #define VALIDATE 0
  5708. #define RENEW 1
  5709.  
  5710. /* stripped down version of krb5_mk_req */
  5711. static krb5_error_code
  5712. #ifdef CK_ANSIC
  5713. krb5_validate_tgt( krb5_context context,
  5714.                    krb5_ccache ccache,
  5715.                    krb5_principal     server, /* tgtname */
  5716.                    krb5_data *outbuf )
  5717. #else
  5718. krb5_validate_tgt(context, ccache, server, outbuf)
  5719.      krb5_context context;
  5720.      krb5_ccache ccache;
  5721.      krb5_principal     server; /* tgtname */
  5722.      krb5_data *outbuf;
  5723. #endif
  5724. {
  5725.     return krb5_tgt_gen(context, ccache, server, outbuf, VALIDATE);
  5726. }
  5727.  
  5728. /* stripped down version of krb5_mk_req */
  5729. static krb5_error_code
  5730. #ifdef CK_ANSIC
  5731. krb5_renew_tgt(krb5_context context,
  5732.                 krb5_ccache ccache,
  5733.                 krb5_principal      server, /* tgtname */
  5734.                 krb5_data *outbuf)
  5735. #else
  5736. krb5_renew_tgt(context, ccache, server, outbuf)
  5737.      krb5_context context;
  5738.      krb5_ccache ccache;
  5739.      krb5_principal      server; /* tgtname */
  5740.      krb5_data *outbuf;
  5741. #endif
  5742. {
  5743.     return krb5_tgt_gen(context, ccache, server, outbuf, RENEW);
  5744. }
  5745.  
  5746.  
  5747. /* stripped down version of krb5_mk_req */
  5748. static krb5_error_code
  5749. #ifdef CK_ANSIC
  5750. krb5_tgt_gen(krb5_context context,
  5751.               krb5_ccache ccache,
  5752.               krb5_principal      server, /* tgtname */
  5753.               krb5_data *outbuf,
  5754.               int opt)
  5755. #else
  5756. krb5_tgt_gen(context, ccache, server, outbuf, opt)
  5757.      krb5_context context;
  5758.      krb5_ccache ccache;
  5759.      krb5_principal      server; /* tgtname */
  5760.      krb5_data *outbuf;
  5761.      int opt;
  5762. #endif
  5763. {
  5764.     krb5_error_code       retval;
  5765.     krb5_creds         * credsp;
  5766.     krb5_creds           creds;
  5767.  
  5768.     /* obtain ticket & session key */
  5769.     memset((char *)&creds, 0, sizeof(creds));
  5770.     if ((retval = krb5_copy_principal(context, server, &creds.server)))
  5771.     goto cleanup;
  5772.  
  5773.     if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)))
  5774.     goto cleanup_creds;
  5775.  
  5776.     if (opt == VALIDATE) {
  5777.     if ((retval = krb5_get_credentials_validate(context, 0,
  5778.                             ccache, &creds, &credsp)))
  5779.       goto cleanup_creds;
  5780.     } else {
  5781.     if ((retval = krb5_get_credentials_renew(context, 0,
  5782.                          ccache, &creds, &credsp)))
  5783.       goto cleanup_creds;
  5784.     }
  5785.  
  5786.     /* we don't actually need to do the mk_req, just get the creds. */
  5787. cleanup_creds:
  5788.     krb5_free_cred_contents(context, &creds);
  5789.  
  5790. cleanup:
  5791.  
  5792.     return retval;
  5793. }
  5794. #endif /* KINIT */
  5795. #ifdef KDESTROY
  5796. int
  5797. #ifdef CK_ANSIC
  5798. ck_krb5_destroy(struct krb_op_data * op)
  5799. #else
  5800. ck_krb5_destroy(op) struct krb_op_data * op;
  5801. #endif
  5802. {
  5803.     krb5_context kcontext;
  5804.     krb5_error_code retval;
  5805.     int c;
  5806.     krb5_ccache ccache = NULL;
  5807.     char *cache_name = NULL;
  5808.     int code;
  5809.     int errflg=0;
  5810.     int quiet = 0;
  5811.  
  5812.     if ( !ck_krb5_is_installed() )
  5813.         return(-1);
  5814.  
  5815.     code = krb5_init_context(&kcontext);
  5816.     if (code) {
  5817.         debug(F101,"ck_krb5_destroy while initializing krb5","",code);
  5818.         krb5_errno = code;
  5819.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5820.         return(-1);
  5821.     }
  5822.  
  5823.     code = k5_get_ccache(kcontext,&ccache,op->cache);
  5824.     if (code != 0) {
  5825.         debug(F101,"ck_krb5_destroy while getting ccache",
  5826.                "",code);
  5827.         krb5_free_context(kcontext);
  5828.         krb5_errno = code;
  5829.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5830.         return(-1);
  5831.     }
  5832.  
  5833.     code = krb5_cc_destroy (kcontext, ccache);
  5834.     if (code != 0) {
  5835.     debug(F101,"ck_krb5_destroy while destroying cache","",code);
  5836.         if ( code == KRB5_FCC_NOFILE )
  5837.             printf("No ticket cache to destroy.\r\n");
  5838.         else
  5839.             printf("Ticket cache NOT destroyed!\r\n");
  5840.         krb5_cc_close(kcontext,ccache);
  5841.         krb5_free_context(kcontext);
  5842.         krb5_errno = code;
  5843.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5844.     return(-1);
  5845.     }
  5846.  
  5847.     printf("Tickets destroyed.\r\n");
  5848.     /* Do not call krb5_cc_close() because cache has been destroyed */
  5849.     krb5_free_context(kcontext);
  5850.     krb5_errno = code;
  5851.     makestr(&krb5_errmsg,error_message(krb5_errno));
  5852.     return (0);
  5853. }
  5854. #endif /* KDESTROY */
  5855. #ifdef KLIST
  5856. static int show_flags = 0, show_time = 0, status_only = 0, show_keys = 0;
  5857. static int show_etype = 0, show_addr = 0;
  5858. static char *defname;
  5859. static char *progname;
  5860. static krb5_int32 now;
  5861. static int timestamp_width;
  5862.  
  5863. static char * etype_string KRB5_PROTOTYPE((krb5_enctype ));
  5864. static void show_credential KRB5_PROTOTYPE((krb5_context,
  5865.                                              krb5_creds *));
  5866.  
  5867. static int do_ccache KRB5_PROTOTYPE((krb5_context,char *));
  5868. static int do_keytab KRB5_PROTOTYPE((krb5_context,char *));
  5869. static void printtime KRB5_PROTOTYPE((time_t));
  5870. static void fillit KRB5_PROTOTYPE((int, int));
  5871.  
  5872. #define DEFAULT 0
  5873. #define CCACHE 1
  5874. #define KEYTAB 2
  5875.  
  5876. int
  5877. #ifdef CK_ANSIC
  5878. ck_krb5_list_creds(struct krb_op_data * op, struct krb5_list_cred_data * lc)
  5879. #else
  5880. ck_krb5_list_creds(op,lc)
  5881.     struct krb_op_data * op; struct krb5_list_cred_data * lc;
  5882. #endif
  5883. {
  5884.     krb5_context kcontext;
  5885.     krb5_error_code retval;
  5886.     int code;
  5887.     char *name = op->cache;
  5888.     int mode;
  5889.  
  5890.     if ( !ck_krb5_is_installed() )
  5891.         return(-1);
  5892.  
  5893.     code = krb5_init_context(&kcontext);
  5894.     if (code) {
  5895.         debug(F101,"ck_krb5_list_creds while initializing krb5","",code);
  5896.         krb5_errno = code;
  5897.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5898.         return(-1);
  5899.     }
  5900.  
  5901.     name = op->cache;
  5902.     mode = DEFAULT;
  5903.     show_flags = 0;
  5904.     show_time = 0;
  5905.     status_only = 0;
  5906.     show_keys = 0;
  5907.     show_etype = 0;
  5908.     show_addr = 0;
  5909.  
  5910.     show_flags = lc->flags;
  5911.     show_etype = lc->encryption;
  5912.     show_addr  = lc->addr;
  5913.     show_time = 1;
  5914.     show_keys = 1;
  5915.     mode = CCACHE;
  5916.  
  5917.     if ((code = krb5_timeofday(kcontext, &now))) {
  5918.         if (!status_only)
  5919.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  5920.                    "",code);
  5921.         krb5_free_context(kcontext);
  5922.         krb5_errno = code;
  5923.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5924.         return(-1);
  5925.     }
  5926.     else {
  5927.     char tmp[BUFSIZ];
  5928.  
  5929.     if (!krb5_timestamp_to_sfstring(now, tmp, 20, (char *) NULL) ||
  5930.         !krb5_timestamp_to_sfstring(now, tmp, sizeof(tmp), (char *) NULL))
  5931.         timestamp_width = (int) strlen(tmp);
  5932.     else
  5933.         timestamp_width = 15;
  5934.     }
  5935.  
  5936.     if (mode == DEFAULT || mode == CCACHE)
  5937.      retval = do_ccache(kcontext,name);
  5938.     else
  5939.      retval = do_keytab(kcontext,name);
  5940.     krb5_free_context(kcontext);
  5941.     return(retval);
  5942. }
  5943.  
  5944. static int
  5945. #ifdef CK_ANSIC
  5946. do_keytab(krb5_context kcontext, char * name)
  5947. #else
  5948. do_keytab(kcontext,name) krb5_context kcontext; char * name;
  5949. #endif
  5950. {
  5951.     krb5_keytab kt;
  5952.     krb5_keytab_entry entry;
  5953.     krb5_kt_cursor cursor;
  5954.     char buf[BUFSIZ]; /* hopefully large enough for any type */
  5955.     char *pname;
  5956.     int code = 0;
  5957.  
  5958.     if (name == NULL) {
  5959.         if ((code = krb5_kt_default(kcontext, &kt))) {
  5960.             debug(F101,"ck_krb5_list_creds while getting default keytab",
  5961.                    "",code);
  5962.             krb5_errno = code;
  5963.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5964.             return(-1);
  5965.         }
  5966.     } else {
  5967.         if ((code = krb5_kt_resolve(kcontext, name, &kt))) {
  5968.             debug(F111,"ck_krb5_list_creds while resolving keytab",
  5969.                      name,code);
  5970.             krb5_errno = code;
  5971.             makestr(&krb5_errmsg,error_message(krb5_errno));
  5972.             return(-1);
  5973.         }
  5974.     }
  5975.  
  5976.     if ((code = krb5_kt_get_name(kcontext, kt, buf, BUFSIZ))) {
  5977.         debug(F101,"ck_krb5_list_creds while getting keytab name",
  5978.                "",code);
  5979.         krb5_errno = code;
  5980.         makestr(&krb5_errmsg,error_message(krb5_errno));
  5981.         return(-1);
  5982.     }
  5983.  
  5984.      printf("Keytab name: %s\r\n", buf);
  5985.  
  5986.      if ((code = krb5_kt_start_seq_get(kcontext, kt, &cursor))) {
  5987.          debug(F101,"ck_krb5_list_creds while starting keytab scan",
  5988.                 "",code);
  5989.          krb5_errno = code;
  5990.          makestr(&krb5_errmsg,error_message(krb5_errno));
  5991.          return(-1);
  5992.      }
  5993.  
  5994.      if (show_time) {
  5995.       printf("KVNO Timestamp");
  5996.           fillit(timestamp_width - sizeof("Timestamp") + 2, (int) ' ');
  5997.       printf("Principal\r\n");
  5998.       printf("---- ");
  5999.       fillit(timestamp_width, (int) '-');
  6000.       printf(" ");
  6001.       fillit(78 - timestamp_width - sizeof("KVNO"), (int) '-');
  6002.       printf("\r\n");
  6003.      } else {
  6004.       printf("KVNO Principal\r\n");
  6005.       printf(
  6006. "---- --------------------------------------------------------------------\
  6007. ------\r\n");
  6008.      }
  6009.  
  6010.     while ((code = krb5_kt_next_entry(kcontext, kt, &entry, &cursor)) == 0) {
  6011.         if ((code = krb5_unparse_name(kcontext, entry.principal, &pname))) {
  6012.             debug(F101,"ck_krb5_list_creds while unparsing principal name",
  6013.                    "",code);
  6014.             krb5_errno = code;
  6015.             makestr(&krb5_errmsg,error_message(krb5_errno));
  6016.             return(-1);
  6017.         }
  6018.         printf("%4d ", entry.vno);
  6019.         if (show_time) {
  6020.             printtime(entry.timestamp);
  6021.             printf(" ");
  6022.         }
  6023.         printf("%s", pname);
  6024.         if (show_etype)
  6025.             printf(" (%s) " , etype_string(entry.key.enctype));
  6026.         if (show_keys) {
  6027.             printf(" (0x");
  6028.             {
  6029.                 int i;
  6030.                 for (i = 0; i < entry.key.length; i++)
  6031.                     printf("%02x", entry.key.contents[i]);
  6032.             }
  6033.             printf(")");
  6034.         }
  6035.         printf("\r\n");
  6036.         krb5_free_unparsed_name(kcontext,pname);
  6037.     }
  6038.     if (code && code != KRB5_KT_END) {
  6039.         debug(F101,"ck_krb5_list_creds while scanning keytab",
  6040.                "",code);
  6041.         krb5_errno = code;
  6042.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6043.         return(-1);
  6044.     }
  6045.     if ((code = krb5_kt_end_seq_get(kcontext, kt, &cursor))) {
  6046.         debug(F101,"ck_krb5_list_creds while ending keytab scan",
  6047.                "",code);
  6048.         krb5_errno = code;
  6049.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6050.         return(-1);
  6051.     }
  6052.     krb5_errno = code;
  6053.     makestr(&krb5_errmsg,error_message(krb5_errno));
  6054.     return(0);
  6055. }
  6056.  
  6057. static int
  6058. #ifdef CK_ANSIC
  6059. do_ccache(krb5_context kcontext, char * cc_name)
  6060. #else
  6061. do_ccache(kcontext,name) krb5_context kcontext; char * cc_name;
  6062. #endif
  6063. {
  6064.     krb5_ccache cache = NULL;
  6065.     krb5_cc_cursor cur;
  6066.     krb5_creds creds;
  6067.     krb5_principal princ=NULL;
  6068.     krb5_flags flags=0;
  6069.     krb5_error_code code = 0;
  6070.     int    exit_status = 0;
  6071.  
  6072.     if (status_only)
  6073.     /* exit_status is set back to 0 if a valid tgt is found */
  6074.     exit_status = 1;
  6075.  
  6076.     code = k5_get_ccache(kcontext,&cache,cc_name);
  6077.     if (code != 0) {
  6078.         debug(F111,"do_ccache while getting ccache",
  6079.                error_message(code),code);
  6080.         krb5_errno = code;
  6081.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6082.         return(-1);
  6083.     }
  6084.  
  6085.     flags = 0;                /* turns off OPENCLOSE mode */
  6086.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  6087.     if (code == ENOENT) {
  6088.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  6089.                    krb5_cc_get_name(kcontext, cache),code);
  6090.     } else {
  6091.             debug(F111,
  6092.          "ck_krb5_list_creds while setting cache flags (ticket cache)",
  6093.                   krb5_cc_get_name(kcontext, cache),code);
  6094.     }
  6095.         printf("No ticket File.\r\n");
  6096.         krb5_errno = code;
  6097.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6098.         krb5_cc_close(kcontext,cache);
  6099.     return(-1);
  6100.     }
  6101.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  6102.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  6103.                "",code);
  6104.         krb5_errno = code;
  6105.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6106.         krb5_cc_close(kcontext,cache);
  6107.     return(-1);
  6108.     }
  6109.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  6110.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  6111.                "",code);
  6112.         krb5_errno = code;
  6113.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6114.         krb5_cc_close(kcontext,cache);
  6115.     return(-1);
  6116.     }
  6117.     if (!status_only) {
  6118.     printf("Ticket cache:      %s:%s\r\nDefault principal: %s\r\n\r\n",
  6119.                 krb5_cc_get_type(kcontext, cache),
  6120.                 krb5_cc_get_name(kcontext, cache), defname);
  6121.     printf("Valid starting");
  6122.     fillit(timestamp_width - sizeof("Valid starting") + 3,
  6123.            (int) ' ');
  6124.     printf("Expires");
  6125.     fillit(timestamp_width - sizeof("Expires") + 3,
  6126.            (int) ' ');
  6127.     printf("Service principal\r\n");
  6128.     }
  6129.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  6130.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  6131.                "",code);
  6132.         krb5_errno = code;
  6133.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6134.         krb5_cc_close(kcontext,cache);
  6135.     return(-1);
  6136.     }
  6137.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  6138.     if (status_only) {
  6139.         if (exit_status && creds.server->length == 2 &&
  6140.         strcmp(creds.server->realm.data, princ->realm.data) == 0 &&
  6141.         strcmp((char *)creds.server->data[0].data, "krbtgt") == 0 &&
  6142.         strcmp((char *)creds.server->data[1].data,
  6143.                princ->realm.data) == 0 &&
  6144.         creds.times.endtime > now)
  6145.         exit_status = 0;
  6146.     } else {
  6147.         show_credential(kcontext, &creds);
  6148.     }
  6149.     krb5_free_cred_contents(kcontext, &creds);
  6150.     }
  6151.     printf("\r\n");
  6152.     if (code == KRB5_CC_END || code == KRB5_CC_NOTFOUND) {
  6153.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  6154.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  6155.                    "",code);
  6156.             krb5_errno = code;
  6157.             makestr(&krb5_errmsg,error_message(krb5_errno));
  6158.             krb5_cc_close(kcontext,cache);
  6159.         return(-1);
  6160.     }
  6161.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  6162.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  6163.             debug(F101,"ck_krb5_list_creds while closing ccache",
  6164.                    "",code);
  6165.             krb5_errno = code;
  6166.             makestr(&krb5_errmsg,error_message(krb5_errno));
  6167.             krb5_cc_close(kcontext,cache);
  6168.         return(-1);
  6169.     }
  6170.         krb5_errno = code;
  6171.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6172.         krb5_cc_close(kcontext,cache);
  6173.     return(exit_status);
  6174.     } else {
  6175.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  6176.         krb5_errno = code;
  6177.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6178.         krb5_cc_close(kcontext,cache);
  6179.     return(-1);
  6180.     }
  6181.     krb5_errno = code;
  6182.     makestr(&krb5_errmsg,error_message(krb5_errno));
  6183.     krb5_cc_close(kcontext,cache);
  6184.     return(0);
  6185. }
  6186.  
  6187. static char *
  6188. #ifdef CK_ANSIC
  6189. etype_string(krb5_enctype enctype)
  6190. #else
  6191. etype_string(enctype) krb5_enctype enctype;
  6192. #endif
  6193. {
  6194.     static char buf[12];
  6195.  
  6196.     switch (enctype) {
  6197.     case ENCTYPE_NULL:
  6198.         return "NULL";
  6199.     case ENCTYPE_DES_CBC_CRC:
  6200.     return "DES-CBC-CRC";
  6201.     case ENCTYPE_DES_CBC_MD4:
  6202.     return "DES-CBC-MD4";
  6203.     case ENCTYPE_DES_CBC_MD5:
  6204.     return "DES-CBC-MD5";
  6205.     case ENCTYPE_DES3_CBC_SHA:
  6206.     return "DES3-CBC-SHA";
  6207.     case ENCTYPE_DES_CBC_RAW:
  6208.         return "DES-CBC-RAW";
  6209.     case ENCTYPE_DES3_CBC_RAW:
  6210.         return "DES3-CBC-RAW";
  6211.     case ENCTYPE_DES3_HMAC_SHA1:
  6212.         return "DES3-HMAC-SHA1";
  6213.     case ENCTYPE_DES_HMAC_SHA1:
  6214.         return "DES-HMAC-SHA1";
  6215.     case ENCTYPE_UNKNOWN:
  6216.         return "UNKNOWN";
  6217.     case ENCTYPE_LOCAL_DES3_HMAC_SHA1:
  6218.         return "LOCAL-DES3-HMAC-SHA1";
  6219.     default:
  6220.     sprintf(buf, "etype %d", enctype);
  6221.     return buf;
  6222.     break;
  6223.     }
  6224. }
  6225.  
  6226. static char *
  6227. #ifdef CK_ANSIC
  6228. flags_string(register krb5_creds *cred)
  6229. #else
  6230. flags_string(cred) register krb5_creds *cred;
  6231. #endif
  6232. {
  6233.     static char buf[32];
  6234.     int i = 0;
  6235.  
  6236.     if (cred->ticket_flags & TKT_FLG_FORWARDABLE)
  6237.         buf[i++] = 'F';
  6238.     if (cred->ticket_flags & TKT_FLG_FORWARDED)
  6239.         buf[i++] = 'f';
  6240.     if (cred->ticket_flags & TKT_FLG_PROXIABLE)
  6241.         buf[i++] = 'P';
  6242.     if (cred->ticket_flags & TKT_FLG_PROXY)
  6243.         buf[i++] = 'p';
  6244.     if (cred->ticket_flags & TKT_FLG_MAY_POSTDATE)
  6245.         buf[i++] = 'D';
  6246.     if (cred->ticket_flags & TKT_FLG_POSTDATED)
  6247.         buf[i++] = 'd';
  6248.     if (cred->ticket_flags & TKT_FLG_INVALID)
  6249.         buf[i++] = 'i';
  6250.     if (cred->ticket_flags & TKT_FLG_RENEWABLE)
  6251.         buf[i++] = 'R';
  6252.     if (cred->ticket_flags & TKT_FLG_INITIAL)
  6253.         buf[i++] = 'I';
  6254.     if (cred->ticket_flags & TKT_FLG_HW_AUTH)
  6255.         buf[i++] = 'H';
  6256.     if (cred->ticket_flags & TKT_FLG_PRE_AUTH)
  6257.         buf[i++] = 'A';
  6258.     buf[i] = '\0';
  6259.     return(buf);
  6260. }
  6261.  
  6262. static char   *
  6263. #ifdef CK_ANSIC
  6264. short_date(long   *dp)
  6265. #else
  6266. short_date(dp) long   *dp;
  6267. #endif
  6268. {
  6269.     register char *cp;
  6270.     extern char *ctime();
  6271.     cp = ctime(dp) + 4;
  6272.     cp[15] = '\0';
  6273.     return (cp);
  6274. }
  6275.  
  6276.  
  6277. static VOID
  6278. #ifdef CK_ANSIC
  6279. printtime(time_t tv)
  6280. #else
  6281. printtime(tv) time_t tv;
  6282. #endif
  6283. {
  6284.     char timestring[BUFSIZ];
  6285.     char format[12];
  6286.     char fill;
  6287.  
  6288.     fill = ' ';
  6289.     sprintf(format,"%%-%ds",timestamp_width);
  6290.     if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
  6291.                                      timestring,
  6292.                                      timestamp_width+1,
  6293.                      &fill)) {
  6294.         printf(format,timestring);
  6295.     }
  6296.     else {
  6297.         printf(format,short_date(&tv));
  6298.     }
  6299.  
  6300. }
  6301.  
  6302. static void
  6303. #ifdef CK_ANSIC
  6304. one_addr(krb5_address *a)
  6305. #else
  6306. one_addr(a) krb5_address *a;
  6307. #endif
  6308. {
  6309.     struct hostent *h;
  6310.     extern tcp_rdns;
  6311.  
  6312.     if ((a->addrtype == ADDRTYPE_INET) &&
  6313.         (a->length == 4)) {
  6314.         if (tcp_rdns != SET_OFF) {
  6315.             h = gethostbyaddr(a->contents, 4, AF_INET);
  6316.             if (h) {
  6317.                 printf("%s (%d.%d.%d.%d)", h->h_name,
  6318.             a->contents[0], a->contents[1],
  6319.             a->contents[2], a->contents[3]);
  6320.             }
  6321.         }
  6322.         if (tcp_rdns == SET_OFF || !h) {
  6323.             printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
  6324.                    a->contents[2], a->contents[3]);
  6325.         }
  6326.     } else {
  6327.         printf("unknown addr type %d", a->addrtype);
  6328.     }
  6329. }
  6330.  
  6331. static VOID
  6332. #ifdef CK_ANSIC
  6333. show_credential(krb5_context kcontext, register krb5_creds * cred)
  6334. #else
  6335. show_credential(kcontext, cred)
  6336.     krb5_context        kcontext;
  6337.     register krb5_creds * cred;
  6338. #endif
  6339. {
  6340.     krb5_error_code retval=0;
  6341.     krb5_ticket *tkt=NULL;
  6342.     char *name=NULL, *sname=NULL, *flags=NULL;
  6343.     int    extra_field = 0;
  6344.  
  6345.     retval = krb5_unparse_name(kcontext, cred->client, &name);
  6346.     if (retval) {
  6347.     debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
  6348.         krb5_errno = retval;
  6349.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6350.     return;
  6351.     }
  6352.     retval = krb5_unparse_name(kcontext, cred->server, &sname);
  6353.     if (retval) {
  6354.     debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
  6355.     free(name);
  6356.         krb5_errno = retval;
  6357.         makestr(&krb5_errmsg,error_message(krb5_errno));
  6358.     return;
  6359.     }
  6360.     if (!cred->times.starttime)
  6361.     cred->times.starttime = cred->times.authtime;
  6362.  
  6363.     printtime(cred->times.starttime);
  6364.     printf("  ");
  6365.  
  6366.     if ( time(0) < cred->times.endtime )
  6367.         printtime(cred->times.endtime);
  6368.     else
  6369.         printf("** expired ** ");
  6370.  
  6371.     printf("  %s\r\n", sname);
  6372.  
  6373.     if (strcmp(name, defname)) {
  6374.         printf("   for client %s", name);
  6375.         extra_field++;
  6376.     }
  6377.  
  6378.     if (cred->times.renew_till) {
  6379.     if (!extra_field)
  6380.             printf("   ");
  6381.     else
  6382.             printf(", ");
  6383.     printf("renew until ");
  6384.         printtime(cred->times.renew_till);
  6385.     extra_field += 2;
  6386.     }
  6387.  
  6388.     if (extra_field > 3) {
  6389.     printf("\r\n");
  6390.     extra_field = 0;
  6391.     }
  6392.  
  6393.     if (show_flags) {
  6394.     flags = flags_string(cred);
  6395.     if (flags && *flags) {
  6396.         if (!extra_field)
  6397.         printf("   ");
  6398.         else
  6399.         printf(", ");
  6400.         printf("Flags: %s", flags);
  6401.         extra_field++;
  6402.         }
  6403.     }
  6404.  
  6405.     if (extra_field > 2) {
  6406.     printf("\r\n");
  6407.     extra_field = 0;
  6408.     }
  6409.  
  6410.     if (show_etype) {
  6411.     retval = decode_krb5_ticket(&cred->ticket, &tkt);
  6412.     if (!extra_field)
  6413.         printf("   ");
  6414.     else
  6415.         printf(", ");
  6416.     printf("Etype (skey, tkt): %s, %s ",
  6417.            etype_string(cred->keyblock.enctype),
  6418.            etype_string(tkt->enc_part.enctype));
  6419.     krb5_free_ticket(kcontext, tkt);
  6420.     extra_field++;
  6421.     }
  6422.  
  6423.     /* if any additional info was printed, extra_field is non-zero */
  6424.     if (extra_field)
  6425.     printf("\r\n");
  6426.  
  6427.     if ( show_addr ) {
  6428.         if (!cred->addresses || !cred->addresses[0]) {
  6429.             printf("\tAddresses: (none)\r\n");
  6430.         } else {
  6431.             int i;
  6432.             for (i=0; cred->addresses[i]; i++) {
  6433.         if (i)
  6434.             printf("              ");
  6435.         else
  6436.             printf("   Addresses: ");
  6437.                 one_addr(cred->addresses[i]);
  6438.         printf("\r\n");
  6439.             }
  6440.         }
  6441.     }
  6442.  
  6443.     free(name);
  6444.     free(sname);
  6445.  
  6446.     krb5_errno = retval;
  6447.     makestr(&krb5_errmsg,error_message(krb5_errno));
  6448. }
  6449.  
  6450. static VOID
  6451. #ifdef CK_ANSIC
  6452. fillit(int num, int c)
  6453. #else
  6454. fillit(num, c) int num; int c;
  6455. #endif
  6456. {
  6457.     int i;
  6458.  
  6459.     for (i=0; i<num; i++)
  6460.     printf("%c",c);
  6461. }
  6462. #endif /* KLIST */
  6463. #endif /* KRB5 */
  6464.  
  6465. #ifdef KRB4
  6466. #define KDEBUG 1
  6467. int k4debug = 0;                /* Kerberos 4 runtime debugging */
  6468.  
  6469. #ifdef KINIT
  6470. #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
  6471.  
  6472. #ifdef SNK4
  6473. /* SNK4 is a hardware authentication system used to pre-authenticate    */
  6474. /* a ticket getting ticket.  We do not support this code at the present */
  6475. /* time in Kermit.                                                      */
  6476. void
  6477. get_input(s, size, stream)
  6478. char *s;
  6479. int size;
  6480. FILE *stream;
  6481. {
  6482.     char *p;
  6483.  
  6484.     if (fgets(s, size, stream) == NULL)
  6485.         exit(1);
  6486.     if ( (p = strchr(s, '\n')) != NULL)
  6487.         *p = '\0';
  6488. }
  6489. #endif /* SNK4 */
  6490.  
  6491. #ifdef COMMENT
  6492. static char
  6493. #ifdef CK_ANSIC
  6494. hex_scan_nybble(char c)
  6495. #else
  6496. hex_scan_nybble(c) char c;
  6497. #endif
  6498. {
  6499.     if (c >= '0' && c <= '9')
  6500.         return c - '0';
  6501.     if (c >= 'A' && c <= 'F')
  6502.         return c - 'A' + 10;
  6503.     if (c >= 'a' && c <= 'f')
  6504.         return c - 'a' + 10;
  6505.     return -1;
  6506. }
  6507.  
  6508. /* returns: NULL for ok, pointer to error string for bad input */
  6509. static char*
  6510. #ifdef CK_ANSIC
  6511. hex_scan_four_bytes(char *out, char *in)
  6512. #else
  6513. hex_scan_four_bytes(out, in) char *out; char *in;
  6514. #endif
  6515. {
  6516.     int i;
  6517.     int c;
  6518.     char c1;
  6519.     for (i=0; i<8; i++) {
  6520.         if(!in[i])
  6521.             return "not enough input";
  6522.         c = hex_scan_nybble(in[i]);
  6523.         if(c<0)
  6524.             return "invalid digit";
  6525.         c1 = c;
  6526.         i++;
  6527.         if(!in[i])
  6528.             return "not enough input";
  6529.         c = hex_scan_nybble(in[i]);
  6530.         if(c<0)
  6531.             return "invalid digit";
  6532.         *out++ = (c1 << 4) + c;
  6533.     }
  6534.     switch(in[i]) {
  6535.     case 0:
  6536.     case '\r':
  6537.     case '\n':
  6538.         return NULL;
  6539.     default:
  6540.         return "extra characters at end of input";
  6541.     }
  6542. }
  6543. #endif /* COMMENT */
  6544.  
  6545. /* ck_krb4_initTGT() returns 0 on success */
  6546. int
  6547. #ifdef CK_ANSIC
  6548. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  6549. #else
  6550. ck_krb4_initTGT(op,init)
  6551.     struct krb_op_data * op, struct krb4_init_data * init
  6552. #endif
  6553. {
  6554.     char    aname[ANAME_SZ+1];
  6555.     char    inst[INST_SZ+1];
  6556.     char    realm[REALM_SZ+1];
  6557.     char    *password=NULL;
  6558.     char   *username = NULL;
  6559.     char   *usernameptr=NULL;
  6560.     int     iflag,      /* Instance */
  6561.             rflag,      /* Realm */
  6562.             vflag,      /* Verbose */
  6563.             lflag,      /* Lifetime */
  6564.             pflag,      /* Preauth */
  6565.             lifetime=KRB_DEFAULT_LIFE,   /* Life Time */
  6566.             k_errno;
  6567.     register char *cp;
  6568.     register i;
  6569.  
  6570.     if ( !ck_krb4_is_installed() )
  6571.         return(-1);
  6572.  
  6573.     *inst = *realm = '\0';
  6574.     iflag = rflag = vflag = lflag = pflag = 0;
  6575.  
  6576.     vflag = init->verbose;
  6577.     pflag = init->preauth;
  6578.  
  6579.     if ( init->lifetime ) {
  6580.         lifetime = init->lifetime<5?1:init->lifetime/5;
  6581.         if ( lifetime > 255 ) lifetime = 255;
  6582.     }
  6583.     else
  6584.         lifetime = KRB_DEFAULT_LIFE;
  6585.  
  6586.     username = init->principal;
  6587.     password = init->password;
  6588.  
  6589.     if (username && username[0] &&
  6590.     (k_errno = kname_parse(aname, inst, realm, username))
  6591.     != AUTH_SUCCESS) {
  6592.         krb4_errno = k_errno;
  6593.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6594.     printf("%s\r\n", krb_get_err_text_entry(k_errno));
  6595.     iflag = rflag = 1;
  6596.     username = NULL;
  6597.     }
  6598.  
  6599.     if ( init->realm ) {
  6600.         ckstrncpy(realm,init->realm,REALM_SZ);
  6601.     }
  6602.  
  6603.     if ( init->instance ) {
  6604.         ckstrncpy(inst,init->instance, INST_SZ);
  6605.     }
  6606.  
  6607. #ifdef COMMENT
  6608.     if ( vflag )
  6609.         printf("Kerberos IV initialization\r\n");
  6610. #endif /* COMMENT */
  6611.  
  6612.     if (!username || !username[0]) {
  6613.         debug(F100,"ck_krb4_initTGT no username specified","",0);
  6614.         printf("?Invalid principal specified.\r\n");
  6615.         krb4_errno = 0;
  6616.         makestr(&krb4_errmsg,"No principal specified");
  6617.         return(-1);
  6618.     }
  6619.     if (!*realm) {
  6620.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
  6621.     }
  6622.  
  6623.     if (pflag) {
  6624.         k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
  6625.                                              "krbtgt", realm,
  6626.                                              lifetime,
  6627.                                              password[0]? password:
  6628.                                              NULL);
  6629.     if (k_errno == -1) {    /* preauth method not available */
  6630.         k_errno = krb_get_pw_in_tkt(aname,
  6631.                      inst, realm,
  6632.                      "krbtgt", realm,
  6633.                      lifetime,
  6634.                      password[0]? password:
  6635.                      NULL);
  6636.     }
  6637.     } else {
  6638.         k_errno = krb_get_pw_in_tkt(aname,
  6639.                                      inst, realm,
  6640.                                      "krbtgt", realm,
  6641.                                      lifetime,
  6642.                                      password[0]? password:
  6643.                                      NULL);
  6644.     }
  6645.  
  6646.     if (k_errno) {
  6647.         printf("%s for principal %s%s%s@%s\r\n",
  6648.         krb_get_err_text_entry(k_errno), aname,
  6649.                 inst[0]?".":"", inst, realm);
  6650.         krb4_errno = k_errno;
  6651.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6652.     return(-1);
  6653.     } else if (vflag) {
  6654.     printf("Result from realm %s: ", realm);
  6655.     printf("%s\r\n", krb_get_err_text_entry(k_errno));
  6656.     }
  6657.     krb4_errno = k_errno;
  6658.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6659.     return(0);
  6660. }
  6661. #endif /* KINIT */
  6662. #ifdef KDESTROY
  6663. int
  6664. #ifdef CK_ANSIC
  6665. ck_krb4_destroy(struct krb_op_data * op)
  6666. #else
  6667. ck_krb4_destroy(op) struct krb_op_data * op;
  6668. #endif
  6669. {
  6670.     int k_errno=0;
  6671.  
  6672.     if ( !ck_krb4_is_installed() )
  6673.         return(-1);
  6674.  
  6675.     k_errno = dest_tkt();
  6676.  
  6677.     krb4_errno = k_errno;
  6678.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6679.  
  6680.     if (k_errno == 0)
  6681.         printf("Tickets destroyed.\r\n");
  6682.     else if (k_errno == RET_TKFIL)
  6683.         printf("No tickets to destroy.\r\n");
  6684.     else {
  6685.         printf("Tickets MAY NOT be destroyed.\r\n");
  6686.         return(-1);
  6687.     }
  6688.     return(0);
  6689. }
  6690. #endif /* KDESTROY */
  6691. #ifdef KLIST
  6692. _PROTOTYP(static int display_tktfile,(char *, int, int, int));
  6693.  
  6694. int
  6695. #ifdef CK_ANSIC
  6696. ck_krb4_list_creds(struct krb_op_data * op)
  6697. #else
  6698. ck_krb4_list_creds(op) struct krb_op_data * op;
  6699. #endif
  6700. {
  6701.     int     long_form = 1;
  6702.     int     tgt_test = 0;
  6703.     int     do_srvtab = 0;
  6704.     int        show_kvnos = 0;
  6705.     char   *tkt_file = NULL;
  6706.  
  6707.     if ( !ck_krb4_is_installed() )
  6708.         return(-1);
  6709.  
  6710.     if ( op->cache )
  6711.         tkt_file = op->cache;
  6712.  
  6713.     if ( k4debug ) {
  6714.         show_kvnos = 1;
  6715.     }
  6716.  
  6717.     if (do_srvtab)
  6718.     return(display_srvtab(tkt_file));
  6719.     else
  6720.     return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
  6721. }
  6722.  
  6723. #ifndef KRB5
  6724. static int timestamp_width=0;
  6725.  
  6726. static char   *
  6727. #ifdef CK_ANSIC
  6728. short_date(long   *dp)
  6729. #else
  6730. short_date(dp) long   *dp;
  6731. #endif
  6732. {
  6733.     register char *cp;
  6734.     extern char *ctime();
  6735.     cp = ctime(dp) + 4;
  6736.     cp[15] = '\0';
  6737.     return (cp);
  6738. }
  6739.  
  6740.  
  6741. static VOID
  6742. #ifdef CK_ANSIC
  6743. printtime(time_t tv)
  6744. #else
  6745. printtime(tv) time_t tv;
  6746. #endif
  6747. {
  6748.     char timestring[BUFSIZ];
  6749.     char format[12];
  6750.     char fill;
  6751.  
  6752.     fill = ' ';
  6753.     sprintf(format,"%%-%ds",timestamp_width);
  6754.     printf(format,short_date(&tv));
  6755. }
  6756. #endif /* KRB5 */
  6757.  
  6758. static int
  6759. #ifdef CK_ANSIC
  6760. display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
  6761. #else
  6762. display_tktfile(file,tgt_test,long_form,show_kvnos)
  6763.     char *file; int tgt_test; int long_form; int show_kvnos;
  6764. #endif
  6765. {
  6766.     char    pname[ANAME_SZ];
  6767.     char    pinst[INST_SZ];
  6768.     char    prealm[REALM_SZ];
  6769.     char    buf1[20], buf2[20];
  6770.     int     k_errno;
  6771. #ifdef OS2
  6772.     LEASH_CREDENTIALS creds;
  6773. #else /* OS2 */
  6774.     CREDENTIALS creds;
  6775. #endif /* OS2 */
  6776.     int     header = 1;
  6777.  
  6778.     file = tkt_string();
  6779.  
  6780.     if (long_form) {
  6781.     printf("Ticket cache:      %s\r\n", file);
  6782.     }
  6783.  
  6784.     /*
  6785.      * Since krb_get_tf_realm will return a ticket_file error,
  6786.      * we will call tf_init and tf_close first to filter out
  6787.      * things like no ticket file.  Otherwise, the error that
  6788.      * the user would see would be
  6789.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  6790.      * instead of
  6791.      * klist: No ticket file (tf_util)
  6792.      */
  6793.  
  6794.     /* Open ticket file */
  6795.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  6796.     if (!tgt_test)
  6797.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  6798.         krb4_errno = k_errno;
  6799.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6800.         return(-1);
  6801.     }
  6802.  
  6803.  
  6804.     /* Close ticket file */
  6805.     (void) tf_close();
  6806.  
  6807.     /*
  6808.      * We must find the realm of the ticket file here before calling
  6809.      * tf_init because since the realm of the ticket file is not
  6810.      * really stored in the principal section of the file, the
  6811.      * routine we use must itself call tf_init and tf_close.
  6812.      */
  6813.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  6814.     if (!tgt_test)
  6815.         printf("can't find realm of ticket file: %s\r\n",
  6816.             krb_get_err_text_entry (k_errno));
  6817.         krb4_errno = k_errno;
  6818.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6819.     return(-1);
  6820.     }
  6821.  
  6822.     /* Open ticket file */
  6823.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  6824.     if (!tgt_test)
  6825.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  6826.         krb4_errno = k_errno;
  6827.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6828.     return(-1);
  6829.     }
  6830.     /* Get principal name and instance */
  6831.     if ((k_errno = tf_get_pname(pname)) ||
  6832.          (k_errno = tf_get_pinst(pinst))) {
  6833.         (void) tf_close();
  6834.         if (!tgt_test)
  6835.             printf("%s\r\n", krb_get_err_text_entry (k_errno));
  6836.         krb4_errno = k_errno;
  6837.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6838.         return(-1);
  6839.     }
  6840.  
  6841.     /*
  6842.      * You may think that this is the obvious place to get the
  6843.      * realm of the ticket file, but it can't be done here as the
  6844.      * routine to do this must open the ticket file.  This is why
  6845.      * it was done before tf_init.
  6846.      */
  6847.  
  6848.     if (!tgt_test && long_form)
  6849.     printf("Default principal: %s%s%s%s%s\r\n\r\n", pname,
  6850.            (pinst[0] ? "." : ""), pinst,
  6851.            (prealm[0] ? "@" : ""), prealm);
  6852.  
  6853.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  6854.     if (!tgt_test && long_form && header) {
  6855.         printf("%-15s  %-15s  %s\r\n",
  6856.            "Valid starting", "Expires", "Service principal");
  6857.         header = 0;
  6858.     }
  6859.     if (tgt_test) {
  6860.         creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  6861.         if (!strcmp(creds.service, "krbtgt") &&
  6862.         !strcmp(creds.instance, prealm)) {
  6863.                 krb4_errno = k_errno;
  6864.                 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6865.  
  6866.                 (void) tf_close();
  6867.         if (time(0) < creds.issue_date) {
  6868.             return(0);        /* tgt hasn't expired */
  6869.         } else {
  6870.             return(-1);        /* has expired */
  6871.                 }
  6872.         }
  6873.         continue;            /* not a tgt */
  6874.     }
  6875.     if (long_form) {
  6876.             timestamp_width = 17;       /* for k5 display function */
  6877.                                         /* if available            */
  6878.             printtime(creds.issue_date);
  6879.         creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  6880.             if ( time(0) < creds.issue_date )
  6881.                 printtime(creds.issue_date);
  6882.             else
  6883.                 printf("*** expired ***  ");
  6884.     }
  6885.         if (show_kvnos)
  6886.       printf("%s%s%s%s%s (%d)\r\n",
  6887.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  6888.          (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
  6889.     else
  6890.       printf("%s%s%s%s%s\r\n",
  6891.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  6892.          (creds.realm[0] ? "@" : ""), creds.realm);
  6893.  
  6894. #ifdef OS2
  6895.     if ( creds.address[0] )
  6896.         printf("   Address: %s\r\n",creds.address);
  6897. #endif /* OS2 */
  6898.     }
  6899.  
  6900.     (void) tf_close();
  6901.  
  6902.     if (tgt_test) {
  6903.     return(-1);
  6904.     }/* no tgt found */
  6905.     if (header && long_form && k_errno == EOF) {
  6906.     printf("No tickets in file.\r\n");
  6907.     }
  6908.     krb4_errno = k_errno;
  6909.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  6910.     return(0);
  6911. }
  6912.  
  6913. #ifdef COMMENT
  6914. /* Just so we remember what the command line interface looked like */
  6915. usage()
  6916. {
  6917.     printf(
  6918.     "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]\r\n");
  6919.     return(-1);
  6920. }
  6921. #endif /* COMMENT */
  6922.  
  6923. /* adapted from getst() in librkb */
  6924. /*
  6925.  * ok_getst() takes a file descriptor, a string and a count.  It reads
  6926.  * from the file until either it has read "count" characters, or until
  6927.  * it reads a null byte.  When finished, what has been read exists in
  6928.  * the given string "s".  If "count" characters were actually read, the
  6929.  * last is changed to a null, so the returned string is always null-
  6930.  * terminated.  ok_getst() returns the number of characters read, including
  6931.  * the null terminator.
  6932.  *
  6933.  * If there is a read error, it returns -1 (like the read(2) system call)
  6934.  */
  6935.  
  6936. static int
  6937. #ifdef CK_ANSIC
  6938. ok_getst(int fd, register char *s, int n)
  6939. #else
  6940. ok_getst(fd, s, n) int fd; register char *s; int n;
  6941. #endif
  6942. {
  6943.     register int count = n;
  6944.     int err;
  6945.     while ((err = read(fd, s, 1)) > 0 && --count)
  6946.         if (*s++ == '\0')
  6947.             return (n - count);
  6948.     if (err < 0)
  6949.     return(-1);
  6950.     *s = '\0';
  6951.     return (n - count);
  6952. }
  6953.  
  6954. int
  6955. #ifdef CK_ANSIC
  6956. display_srvtab(char *file)
  6957. #else
  6958. display_srvtab(file) char *file;
  6959. #endif
  6960. {
  6961.     int stab;
  6962.     char serv[SNAME_SZ];
  6963.     char inst[INST_SZ];
  6964.     char rlm[REALM_SZ];
  6965.     unsigned char key[8];
  6966.     unsigned char vno;
  6967.     int count;
  6968.  
  6969.     printf("Server key file:   %s\r\n", file);
  6970.  
  6971.     if ((stab = open(file, O_RDONLY, 0400)) < 0) {
  6972.     perror(file);
  6973.     return(-1);
  6974.     }
  6975.     printf("%-15s %-15s %-10s %s\r\n","Service","Instance","Realm",
  6976.        "Key Version");
  6977.     printf("------------------------------------------------------\r\n");
  6978.  
  6979.     /* argh. getst doesn't return error codes, it silently fails */
  6980.     while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
  6981.        && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
  6982.        && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
  6983.     if (((count = read(stab,(char *) &vno,1)) != 1) ||
  6984.          ((count = read(stab,(char *) key,8)) != 8)) {
  6985.         if (count < 0)
  6986.         perror("reading from key file");
  6987.         else
  6988.         printf("key file truncated\r\n");
  6989.         return(-1);
  6990.     }
  6991.     printf("%-15s %-15s %-15s %d\r\n",serv,inst,rlm,vno);
  6992.     }
  6993.     if (count < 0)
  6994.     perror(file);
  6995.     (void) close(stab);
  6996.     return(0);
  6997. }
  6998. #endif /* KLIST */
  6999. #else /* KRB4 */
  7000. int
  7001. ck_krb4_autoget_TGT(char * dummy)
  7002. {
  7003.     return(-1);
  7004. }
  7005. #ifdef CK_KERBEROS
  7006. int
  7007. #ifdef CK_ANSIC
  7008. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  7009. #else
  7010. ck_krb4_initTGT(op,init)
  7011.     struct krb_op_data * op, struct krb4_init_data * init
  7012. #endif
  7013. {
  7014.     return(-1);
  7015. }
  7016.  
  7017. #ifdef CK_ANSIC
  7018. ck_krb4_destroy(struct krb_op_data * op)
  7019. #else
  7020. ck_krb4_destroy(op) struct krb_op_data * op;
  7021. #endif
  7022. {
  7023.     return(-1);
  7024. }
  7025. int
  7026. #ifdef CK_ANSIC
  7027. ck_krb4_list_creds(struct krb_op_data * op)
  7028. #else
  7029. ck_krb4_list_creds(op) struct krb_op_data * op;
  7030. #endif
  7031. {
  7032.     return(-1);
  7033. }
  7034. #else /* CK_KERBEROS */
  7035. int ck_krb4_initTGT(void * a, void *b)
  7036. {
  7037.     return(-1);
  7038. }
  7039. int ck_krb4_destroy(void *a)
  7040. {
  7041.     return(-1);
  7042. }
  7043. int ck_krb4_list_creds(void *a)
  7044. {
  7045.     return(-1);
  7046. }
  7047. #endif /* CK_KERBEROS */
  7048. #endif /* KRB4 */
  7049.  
  7050. /* The following functions are used to implement the Kermit Script Language */
  7051. /* functions                                                                */
  7052.  
  7053. struct tkt_list_item {
  7054.     char * name;
  7055.     struct tkt_list_item * next;
  7056. };
  7057.  
  7058. static struct tkt_list_item * k4_tkt_list = NULL;
  7059.  
  7060. int
  7061. #ifdef CK_ANSIC
  7062. ck_krb4_get_tkts(VOID)
  7063. #else
  7064. ck_krb4_get_tkts()
  7065. #endif
  7066. {
  7067. #ifdef KRB4
  7068.     char   *file=NULL;
  7069.     char    pname[ANAME_SZ];
  7070.     char    pinst[INST_SZ];
  7071.     char    prealm[REALM_SZ];
  7072.     char    buf1[20], buf2[20];
  7073.     int     k_errno;
  7074. #ifdef OS2
  7075.     LEASH_CREDENTIALS creds;
  7076. #else /* OS2 */
  7077.     CREDENTIALS creds;
  7078. #endif /* OS2 */
  7079.     int     tkt_count=0;
  7080.     struct  tkt_list_item ** list = &k4_tkt_list;
  7081.  
  7082.     while ( k4_tkt_list ) {
  7083.         struct tkt_list_item * next;
  7084.         next = k4_tkt_list->next;
  7085.         free(k4_tkt_list->name);
  7086.         free(k4_tkt_list);
  7087.         k4_tkt_list = next;
  7088.     }
  7089.  
  7090.     if ( !ck_krb4_is_installed() )
  7091.         return(-1);
  7092.  
  7093.     file = tkt_string();
  7094.  
  7095.     /*
  7096.      * Since krb_get_tf_realm will return a ticket_file error,
  7097.      * we will call tf_init and tf_close first to filter out
  7098.      * things like no ticket file.  Otherwise, the error that
  7099.      * the user would see would be
  7100.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  7101.      * instead of
  7102.      * klist: No ticket file (tf_util)
  7103.      */
  7104.  
  7105.     /* Open ticket file */
  7106.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  7107.         return(-1);
  7108.     }
  7109.  
  7110.     /* Close ticket file */
  7111.     (void) tf_close();
  7112.  
  7113.     /*
  7114.      * We must find the realm of the ticket file here before calling
  7115.      * tf_init because since the realm of the ticket file is not
  7116.      * really stored in the principal section of the file, the
  7117.      * routine we use must itself call tf_init and tf_close.
  7118.      */
  7119.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  7120.     return(-1);
  7121.     }
  7122.  
  7123.     /* Open ticket file */
  7124.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  7125.     return(-1);
  7126.     }
  7127.     /* Get principal name and instance */
  7128.     if ((k_errno = tf_get_pname(pname)) ||
  7129.          (k_errno = tf_get_pinst(pinst))) {
  7130.         return(-1);
  7131.     }
  7132.  
  7133.     /*
  7134.      * You may think that this is the obvious place to get the
  7135.      * realm of the ticket file, but it can't be done here as the
  7136.      * routine to do this must open the ticket file.  This is why
  7137.      * it was done before tf_init.
  7138.      */
  7139.  
  7140.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  7141.         char tkt_buf[256];
  7142.         sprintf(tkt_buf,"%s%s%s%s%s",
  7143.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  7144.          (creds.realm[0] ? "@" : ""), creds.realm);
  7145.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  7146.         (*list)->name = strdup(tkt_buf);
  7147.         (*list)->next = NULL;
  7148.         list = &((*list)->next);
  7149.         tkt_count++;
  7150.     }
  7151.  
  7152.     tf_close();
  7153.     return(tkt_count);
  7154. #else /* KRB4 */
  7155.     return(0);
  7156. #endif /* KRB4 */
  7157. }
  7158.  
  7159. char *
  7160. #ifdef CK_ANSIC
  7161. ck_krb4_get_next_tkt(VOID)
  7162. #else
  7163. ck_krb4_get_next_tkt()
  7164. #endif
  7165. {
  7166. #ifdef KRB4
  7167.     static char * s=NULL;
  7168.     struct tkt_list_item * next=NULL;
  7169.  
  7170.     if ( s ) {
  7171.         free(s);
  7172.         s = NULL;
  7173.     }
  7174.  
  7175.     if ( k4_tkt_list == NULL )
  7176.         return(NULL);
  7177.  
  7178.     next = k4_tkt_list->next;
  7179.     s = k4_tkt_list->name;
  7180.     free(k4_tkt_list);
  7181.     k4_tkt_list = next;
  7182.     return(s);
  7183. #else /* KRB4 */
  7184.     return(NULL);
  7185. #endif /* KRB4 */
  7186. }
  7187.  
  7188. int
  7189. #ifdef CK_ANSIC
  7190. ck_krb4_tkt_isvalid(char * tktname)
  7191. #else
  7192. ck_krb4_tkt_isvalid(tktname) char * tktname;
  7193. #endif
  7194. {
  7195. #ifdef KRB4
  7196.     char   *file=NULL;
  7197.     char    pname[ANAME_SZ];
  7198.     char    pinst[INST_SZ];
  7199.     char    prealm[REALM_SZ];
  7200.     char    buf1[20], buf2[20];
  7201.     int     k_errno;
  7202.     time_t  issue_t, expire_t, now_t;
  7203. #ifdef OS2
  7204.     LEASH_CREDENTIALS creds;
  7205. #else /* OS2 */
  7206.     CREDENTIALS creds;
  7207. #endif /* OS2 */
  7208.  
  7209.     if ( !ck_krb4_is_installed() )
  7210.         return(-1);
  7211.  
  7212.     debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
  7213.     file = tkt_string();
  7214.  
  7215.     /*
  7216.      * Since krb_get_tf_realm will return a ticket_file error,
  7217.      * we will call tf_init and tf_close first to filter out
  7218.      * things like no ticket file.  Otherwise, the error that
  7219.      * the user would see would be
  7220.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  7221.      * instead of
  7222.      * klist: No ticket file (tf_util)
  7223.      */
  7224.  
  7225.     /* Open ticket file */
  7226.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  7227.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  7228.         return(-1);
  7229.     }
  7230.  
  7231.     /* Close ticket file */
  7232.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7233.     (void) tf_close();
  7234.  
  7235.     /*
  7236.      * We must find the realm of the ticket file here before calling
  7237.      * tf_init because since the realm of the ticket file is not
  7238.      * really stored in the principal section of the file, the
  7239.      * routine we use must itself call tf_init and tf_close.
  7240.      */
  7241.     debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
  7242.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  7243.     return(-1);
  7244.     }
  7245.  
  7246.     /* Open ticket file */
  7247.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  7248.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  7249.     return(-1);
  7250.     }
  7251.     /* Get principal name and instance */
  7252.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
  7253.     if ((k_errno = tf_get_pname(pname)) ||
  7254.          (k_errno = tf_get_pinst(pinst))) {
  7255.  
  7256.         /* Close ticket file */
  7257.         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7258.         (void) tf_close();
  7259.  
  7260.         return(-1);
  7261.     }
  7262.  
  7263.     /*
  7264.      * You may think that this is the obvious place to get the
  7265.      * realm of the ticket file, but it can't be done here as the
  7266.      * routine to do this must open the ticket file.  This is why
  7267.      * it was done before tf_init.
  7268.      */
  7269.  
  7270.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
  7271.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  7272.         char tkt_buf[256];
  7273.         sprintf(tkt_buf,"%s%s%s%s%s",
  7274.          creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  7275.          (creds.realm[0] ? "@" : ""), creds.realm);
  7276.         if ( !strcmp(tktname,tkt_buf) ) {
  7277.  
  7278.             /* we found the ticket we are looking for */
  7279.             issue_t = creds.issue_date;
  7280.             expire_t = creds.issue_date
  7281.                 + ((unsigned char) creds.lifetime) * 5 * 60;
  7282.             now_t = time(0);
  7283.  
  7284.             /* We add a 5 minutes fudge factor to compensate for potential */
  7285.             /* clock skew errors between the KDC and K95's host OS         */
  7286.  
  7287.             if ( now_t >= (issue_t-300) &&
  7288.                  now_t < expire_t)
  7289.             {
  7290. #ifdef OS2
  7291. #ifdef CHECKADDRS
  7292.         if ( krb4_checkaddrs ) {
  7293.             extern char myipaddr[20];       /* From ckcnet.c */
  7294.             if ( !myipaddr[0] ) {
  7295.             int i;
  7296.             char buf[60];
  7297.             for ( i=0;i<64;i++ ) {
  7298.                 if ( getlocalipaddrs(buf,60,i) < 0 )
  7299.                 break;
  7300.  
  7301.                 if ( !strcmp(buf,creds.address) ) {
  7302.                 /* Close ticket file */
  7303.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7304.                 (void) tf_close();
  7305.                 return(1); /* They're the same */
  7306.                 }
  7307.             }
  7308.             /* Close ticket file */
  7309.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7310.             (void) tf_close();
  7311.             return(0);                  /* They're different */
  7312.             } else if ( strcmp(myipaddr,creds.address) ) {
  7313.             /* Close ticket file */
  7314.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7315.             (void) tf_close();
  7316.             return(0);                  /* They're different */
  7317.             }
  7318.             else {
  7319.             /* Close ticket file */
  7320.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7321.             (void) tf_close();
  7322.             return(1);                  /* They're the same */
  7323.             }
  7324.         } else {
  7325.             /* Close ticket file */
  7326.             debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7327.             (void) tf_close();
  7328.             return(1);                  /* They're the same */
  7329.         }
  7330. #else /* CHECKADDRS */
  7331.                 /* Close ticket file */
  7332.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7333.                 (void) tf_close();
  7334.                 return(1);      /* valid but no ip address check */
  7335. #endif /* CHECKADDRS */
  7336. #else /* OS2 */
  7337.                 /* Close ticket file */
  7338.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7339.                 (void) tf_close();
  7340.                 return(1);      /* Valid but no ip address check */
  7341. #endif /* OS2 */
  7342.             }
  7343.             else {
  7344.                 /* Close ticket file */
  7345.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7346.                 (void) tf_close();
  7347.                 return(0);      /* expired or otherwise invalid */
  7348.             }
  7349.         }
  7350.     }
  7351.     /* Close ticket file */
  7352.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  7353.     (void) tf_close();
  7354.     return(0);                  /* could not find the desired ticket */
  7355. #else /* KRB4 */
  7356.     return(-1);
  7357. #endif /* KRB4 */
  7358. }
  7359.  
  7360. int
  7361. #ifdef CK_ANSIC
  7362. ck_krb4_is_tgt_valid(VOID)
  7363. #else
  7364. ck_krb4_is_tgt_valid()
  7365. #endif
  7366. {
  7367. #ifdef KRB4
  7368.     char tgt[256];
  7369.     char * s;
  7370.     int rc = 0;
  7371.  
  7372.     s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
  7373.     sprintf(tgt,"krbtgt.%s@%s",s,s);
  7374.     rc = ck_krb4_tkt_isvalid(tgt);
  7375.     debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
  7376.     return(rc > 0);
  7377. #else /* KRB4 */
  7378.     return(0);
  7379. #endif /* KRB4 */
  7380. }
  7381.  
  7382. int
  7383. #ifdef CK_ANSIC
  7384. ck_krb4_tkt_time(char * tktname)
  7385. #else
  7386. ck_krb4_tkt_time(tktname) char * tktname;
  7387. #endif
  7388. {
  7389. #ifdef KRB4
  7390.     char   *file=NULL;
  7391.     char    pname[ANAME_SZ];
  7392.     char    pinst[INST_SZ];
  7393.     char    prealm[REALM_SZ];
  7394.     char    buf1[20], buf2[20];
  7395.     int     k_errno;
  7396. #ifdef OS2
  7397.     LEASH_CREDENTIALS creds;
  7398. #else /* OS2 */
  7399.     CREDENTIALS creds;
  7400. #endif /* OS2 */
  7401.  
  7402.     if ( !ck_krb4_is_installed() )
  7403.         return(-1);
  7404.  
  7405.     file = tkt_string();
  7406.  
  7407.     /*
  7408.      * Since krb_get_tf_realm will return a ticket_file error,
  7409.      * we will call tf_init and tf_close first to filter out
  7410.      * things like no ticket file.  Otherwise, the error that
  7411.      * the user would see would be
  7412.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  7413.      * instead of
  7414.      * klist: No ticket file (tf_util)
  7415.      */
  7416.  
  7417.     /* Open ticket file */
  7418.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  7419.         return(-1);
  7420.     }
  7421.  
  7422.     /* Close ticket file */
  7423.     (void) tf_close();
  7424.  
  7425.     /*
  7426.      * We must find the realm of the ticket file here before calling
  7427.      * tf_init because since the realm of the ticket file is not
  7428.      * really stored in the principal section of the file, the
  7429.      * routine we use must itself call tf_init and tf_close.
  7430.      */
  7431.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  7432.     return(-1);
  7433.     }
  7434.  
  7435.     /* Open ticket file */
  7436.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  7437.     return(-1);
  7438.     }
  7439.     /* Get principal name and instance */
  7440.     if ((k_errno = tf_get_pname(pname)) ||
  7441.          (k_errno = tf_get_pinst(pinst))) {
  7442.         tf_close();
  7443.         return(-1);
  7444.     }
  7445.  
  7446.     /*
  7447.      * You may think that this is the obvious place to get the
  7448.      * realm of the ticket file, but it can't be done here as the
  7449.      * routine to do this must open the ticket file.  This is why
  7450.      * it was done before tf_init.
  7451.      */
  7452.  
  7453.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  7454.         char tkt_buf[256];
  7455.         sprintf(tkt_buf,"%s%s%s%s%s",
  7456.          creds.service, (creds.instance[0] ? "." : ""),
  7457.                  creds.instance,
  7458.          (creds.realm[0] ? "@" : ""), creds.realm);
  7459.         if ( !strcmp(tktname,tkt_buf) ) {
  7460.             /* we found the ticket we are looking for */
  7461.             int n = (creds.issue_date
  7462.                       + (((unsigned char) creds.lifetime) * 5 * 60))
  7463.                 - time(0);
  7464.             tf_close();
  7465.             return(n <= 0 ? 0 : n);
  7466.         }
  7467.     }
  7468.     tf_close();
  7469.     return(0);                  /* could not find the desired ticket */
  7470. #else /* KRB4 */
  7471.     return(-1);
  7472. #endif /* KRB4 */
  7473. }
  7474.  
  7475. char *
  7476. #ifdef CK_ANSIC
  7477. ck_krb4_getrealm(void)
  7478. #else
  7479. ck_krb4_getrealm()
  7480. #endif
  7481. {
  7482. #ifdef KRB4
  7483.     char   *file=NULL;
  7484.     int     k_errno;
  7485.     static char realm[256]="";
  7486.     realm[0]='\0';
  7487.  
  7488.     if ( !ck_krb4_is_installed() )
  7489.         return(realm);
  7490.  
  7491.     /* Try to get realm from ticket file */
  7492.     /* If failure get the local realm    */
  7493.  
  7494.     /*
  7495.     * Since krb_get_tf_realm will return a ticket_file error,
  7496.     * we will call tf_init and tf_close first to filter out
  7497.     * things like no ticket file.
  7498.     */
  7499.  
  7500.     /* Open ticket file */
  7501.     file = tkt_string();
  7502.     if (file == NULL || !file[0])
  7503.         return(realm);
  7504.  
  7505.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  7506.         /* Close ticket file */
  7507.         (void) tf_close();
  7508.  
  7509.         k_errno = krb_get_tf_realm(file, realm);
  7510.     }
  7511.     if (k_errno != KSUCCESS) {
  7512.         k_errno = krb_get_lrealm(realm, 1);
  7513.     }
  7514.     return(realm);
  7515. #else /* KRB4 */
  7516.     return("");
  7517. #endif /* KRB4 */
  7518. }
  7519.  
  7520. char *
  7521. #ifdef CK_ANSIC
  7522. ck_krb4_getprincipal(void)
  7523. #else
  7524. ck_krb4_getprincipal()
  7525. #endif
  7526. {
  7527. #ifdef KRB4
  7528.     char   *file=NULL;
  7529.     int     k_errno;
  7530.     static char principal[256]="";
  7531.     char        instance[256]="";
  7532.     char        realm[256]="";
  7533.     principal[0]='\0';
  7534.  
  7535.     if ( !ck_krb4_is_installed() )
  7536.         return(principal);
  7537.  
  7538.     /* Try to get realm from ticket file */
  7539.     /* If failure get the local realm    */
  7540.  
  7541.     /*
  7542.     * Since krb_get_tf_realm will return a ticket_file error,
  7543.     * we will call tf_init and tf_close first to filter out
  7544.     * things like no ticket file.
  7545.     */
  7546.  
  7547.     /* Open ticket file */
  7548.     file = tkt_string();
  7549.     if (file == NULL || !file[0])
  7550.         return(principal);
  7551.  
  7552.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  7553.         /* Close ticket file */
  7554.         (void) tf_close();
  7555.  
  7556.         k_errno = krb_get_tf_fullname(file, principal, instance, realm);
  7557.     }
  7558.     return(principal);
  7559. #else /* KRB4 */
  7560.     return("");
  7561. #endif /* KRB4 */
  7562. }
  7563.  
  7564. static struct tkt_list_item * k5_tkt_list = NULL;
  7565.  
  7566. int
  7567. #ifdef CK_ANSIC
  7568. ck_krb5_get_tkts(char * cc_name)
  7569. #else
  7570. ck_krb5_get_tkts(cc_name) char * cc_name;
  7571. #endif
  7572. {
  7573. #ifdef KRB5
  7574.     krb5_context kcontext;
  7575.     krb5_error_code retval;
  7576.     krb5_ccache cache = NULL;
  7577.     krb5_cc_cursor cur;
  7578.     krb5_creds creds;
  7579.     krb5_principal princ=NULL;
  7580.     krb5_flags flags=0;
  7581.     krb5_error_code code=0;
  7582.     int    exit_status = 0;
  7583.  
  7584.     int     tkt_count=0;
  7585.     struct  tkt_list_item ** list = &k5_tkt_list;
  7586.  
  7587.     while ( k5_tkt_list ) {
  7588.         struct tkt_list_item * next;
  7589.         next = k5_tkt_list->next;
  7590.         free(k5_tkt_list->name);
  7591.         free(k5_tkt_list);
  7592.         k5_tkt_list = next;
  7593.     }
  7594.  
  7595.     if ( !ck_krb5_is_installed() )
  7596.         return(-1);
  7597.  
  7598.     retval = krb5_init_context(&kcontext);
  7599.     if (retval) {
  7600.         debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
  7601.         return(-1);
  7602.     }
  7603.  
  7604.     code = k5_get_ccache(kcontext,&cache,cc_name);
  7605.     if (code != 0) {
  7606.         debug(F111,"ck_krb5_get_tkts while getting ccache",
  7607.                error_message(code),code);
  7608.         tkt_count = -1;
  7609.         goto exit_k5_get_tkt;
  7610.     }
  7611.  
  7612.     flags = 0;                /* turns off OPENCLOSE mode */
  7613.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  7614.     if (code == ENOENT) {
  7615.             debug(F111,"ck_krb5_get_tkts (ticket cache)",
  7616.                    krb5_cc_get_name(kcontext, cache),code);
  7617.     } else {
  7618.             debug(F111,
  7619.          "ck_krb5_get_tkts while setting cache flags (ticket cache)",
  7620.                   krb5_cc_get_name(kcontext, cache),code);
  7621.     }
  7622.         tkt_count = -1;
  7623.         goto exit_k5_get_tkt;
  7624.     }
  7625.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  7626.         debug(F101,"ck_krb5_get_tkts while retrieving principal name",
  7627.                "",code);
  7628.         tkt_count = -1;
  7629.         goto exit_k5_get_tkt;
  7630.     }
  7631.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  7632.         debug(F101,"ck_krb5_get_tkts while unparsing principal name",
  7633.                "",code);
  7634.         tkt_count = -1;
  7635.         goto exit_k5_get_tkt;
  7636.     }
  7637.  
  7638.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  7639.         debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
  7640.                "",code);
  7641.         tkt_count = -1;
  7642.         goto exit_k5_get_tkt;
  7643.     }
  7644.  
  7645.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  7646.         char *sname=NULL;
  7647.  
  7648.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  7649.         if (retval) {
  7650.             debug(F101,
  7651.           "ck_krb5_get_tkts while unparsing server name","",retval);
  7652.             tkt_count = -1;
  7653.             goto exit_k5_get_tkt;
  7654.         }
  7655.  
  7656.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  7657.         (*list)->name = sname;
  7658.         (*list)->next = NULL;
  7659.         list = &((*list)->next);
  7660.  
  7661.     krb5_free_cred_contents(kcontext, &creds);
  7662.         tkt_count++;
  7663.     }
  7664.  
  7665.     if (code == KRB5_CC_END) {
  7666.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  7667.             debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
  7668.                    "",code);
  7669.             tkt_count = -1;
  7670.             goto exit_k5_get_tkt;
  7671.     }
  7672.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  7673.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  7674.             debug(F101,"ck_krb5_get_tkts while closing ccache",
  7675.                    "",code);
  7676.             tkt_count = -1;
  7677.             goto exit_k5_get_tkt;
  7678.     }
  7679.     } else {
  7680.         debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
  7681.         tkt_count = -1;
  7682.         goto exit_k5_get_tkt;
  7683.     }
  7684.  
  7685.   exit_k5_get_tkt:
  7686.     krb5_free_principal(kcontext,princ);
  7687.     krb5_free_unparsed_name(kcontext,defname);
  7688.     krb5_cc_close(kcontext,cache);
  7689.     krb5_free_context(kcontext);
  7690.     return(tkt_count);
  7691. #else /* KRB5 */
  7692.     return(0);
  7693. #endif /* KRB5 */
  7694. }
  7695.  
  7696. char *
  7697. #ifdef CK_ANSIC
  7698. ck_krb5_get_next_tkt(VOID)
  7699. #else
  7700. ck_krb5_get_next_tkt()
  7701. #endif
  7702. {
  7703. #ifdef KRB5
  7704.     static char * s=NULL;
  7705.     struct tkt_list_item * next=NULL;
  7706.  
  7707.     if ( s ) {
  7708.         free(s);
  7709.         s = NULL;
  7710.     }
  7711.  
  7712.     if ( k5_tkt_list == NULL )
  7713.         return(NULL);
  7714.  
  7715.     next = k5_tkt_list->next;
  7716.     s = k5_tkt_list->name;
  7717.     free(k5_tkt_list);
  7718.     k5_tkt_list = next;
  7719.     return(s);
  7720. #else /* KRB5 */
  7721.     return(NULL);
  7722. #endif /* KRB5 */
  7723. }
  7724.  
  7725. char *
  7726. #ifdef CK_ANSIC
  7727. ck_krb5_tkt_flags(char * cc_name, char * tktname)
  7728. #else
  7729. ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
  7730. #endif
  7731. {
  7732. #ifdef KRB5
  7733.     krb5_context kcontext;
  7734.     krb5_error_code retval;
  7735.     krb5_ccache cache = NULL;
  7736.     krb5_cc_cursor cur;
  7737.     krb5_creds creds;
  7738.     krb5_principal princ=NULL;
  7739.     krb5_flags flags=0;
  7740.     krb5_error_code code=0;
  7741.     char * flag_str = "";
  7742.  
  7743.     if ( !ck_krb5_is_installed() )
  7744.         return("");
  7745.  
  7746.     retval = krb5_init_context(&kcontext);
  7747.     if (retval) {
  7748.         debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
  7749.         return("");
  7750.     }
  7751.  
  7752.     code = k5_get_ccache(kcontext,&cache,cc_name);
  7753.     if (code != 0) {
  7754.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  7755.                error_message(code),code);
  7756.         goto exit_k5_get_tkt;
  7757.     }
  7758.  
  7759.     flags = 0;                /* turns off OPENCLOSE mode */
  7760.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  7761.     if (code == ENOENT) {
  7762.             debug(F111,"ck_krb5_tkt_flags (ticket cache)",
  7763.                    krb5_cc_get_name(kcontext, cache),code);
  7764.     } else {
  7765.             debug(F111,
  7766.          "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
  7767.                   krb5_cc_get_name(kcontext, cache),code);
  7768.     }
  7769.         retval = -1;
  7770.         goto exit_k5_get_tkt;
  7771.     }
  7772.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  7773.         debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
  7774.                "",code);
  7775.         retval = -1;
  7776.         goto exit_k5_get_tkt;
  7777.     }
  7778.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  7779.         debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
  7780.                "",code);
  7781.         retval = -1;
  7782.         goto exit_k5_get_tkt;
  7783.     }
  7784.  
  7785.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  7786.         debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
  7787.                "",code);
  7788.         retval = -1;
  7789.         goto exit_k5_get_tkt;
  7790.     }
  7791.  
  7792.     if ((code = krb5_timeofday(kcontext, &now))) {
  7793.         if (!status_only)
  7794.             debug(F101,"ck_krb5_tkt_flags while getting time of day.",
  7795.                    "",code);
  7796.         retval = -1;
  7797.         goto exit_k5_get_tkt;
  7798.     }
  7799.  
  7800.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  7801.         char *sname=NULL;
  7802.  
  7803.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  7804.         if (retval) {
  7805.             debug(F101,
  7806.           "ck_krb5_tkt_flags while unparsing server name","",retval);
  7807.             retval = -1;
  7808.             krb5_free_cred_contents(kcontext, &creds);
  7809.             goto exit_k5_get_tkt;
  7810.         }
  7811.  
  7812.         if ( !strcmp(sname,tktname) ) {
  7813.             /* we found the ticket we are looking for */
  7814.  
  7815.             flag_str = flags_string(&creds);
  7816.  
  7817.             krb5_free_cred_contents(kcontext, &creds);
  7818.             code = KRB5_CC_END;
  7819.             break;
  7820.         }
  7821.     krb5_free_cred_contents(kcontext, &creds);
  7822.     }
  7823.  
  7824.     if (code == KRB5_CC_END) {
  7825.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  7826.             debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
  7827.                    "",code);
  7828.             goto exit_k5_get_tkt;
  7829.     }
  7830.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  7831.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  7832.             debug(F101,"ck_krb5_tkt_flags while closing ccache",
  7833.                    "",code);
  7834.             goto exit_k5_get_tkt;
  7835.     }
  7836.     } else {
  7837.         debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
  7838.         goto exit_k5_get_tkt;
  7839.     }
  7840.  
  7841.   exit_k5_get_tkt:
  7842.     krb5_free_principal(kcontext,princ);
  7843.     krb5_free_unparsed_name(kcontext,defname);
  7844.     krb5_cc_close(kcontext,cache);
  7845.     krb5_free_context(kcontext);
  7846.     return(flag_str);
  7847. #else /* KRB5 */
  7848.     return("");
  7849. #endif /* KRB5 */
  7850. }
  7851.  
  7852.  
  7853. int
  7854. #ifdef CK_ANSIC
  7855. ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
  7856. #else
  7857. ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
  7858. #endif
  7859. {
  7860. #ifdef KRB5
  7861.     krb5_context kcontext=NULL;
  7862.     krb5_error_code retval;
  7863.     krb5_ccache cache = NULL;
  7864.     krb5_cc_cursor cur;
  7865.     krb5_creds creds;
  7866.     krb5_principal princ=NULL;
  7867.     krb5_flags flags=0;
  7868.     krb5_error_code code=0;
  7869. #ifdef CHECKADDRS
  7870.     krb5_address **    myAddrs=NULL;
  7871.     krb5_address **    p=NULL;
  7872.     BOOL            Addrfound = FALSE;
  7873. #endif /*CHECKADDRS*/
  7874.  
  7875.     if ( !ck_krb5_is_installed() )
  7876.         return(-1);
  7877.  
  7878.     retval = krb5_init_context(&kcontext);
  7879.     if (retval) {
  7880.         debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
  7881.         return(-1);
  7882.     }
  7883.  
  7884.     code = k5_get_ccache(kcontext,&cache,cc_name);
  7885.     if (code != 0) {
  7886.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  7887.                error_message(code),code);
  7888.         goto exit_k5_get_tkt;
  7889.     }
  7890.  
  7891.     flags = 0;                /* turns off OPENCLOSE mode */
  7892.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  7893.     if (code == ENOENT) {
  7894.             debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
  7895.                    krb5_cc_get_name(kcontext, cache),code);
  7896.     } else {
  7897.             debug(F111,
  7898.         "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
  7899.                   krb5_cc_get_name(kcontext, cache),code);
  7900.     }
  7901.         retval = -1;
  7902.         goto exit_k5_get_tkt;
  7903.     }
  7904.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  7905.         debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
  7906.                "",code);
  7907.         retval = -1;
  7908.         goto exit_k5_get_tkt;
  7909.     }
  7910.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  7911.         debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
  7912.                "",code);
  7913.         retval = -1;
  7914.         goto exit_k5_get_tkt;
  7915.     }
  7916.  
  7917.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  7918.         debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
  7919.                "",code);
  7920.         retval = -1;
  7921.         goto exit_k5_get_tkt;
  7922.     }
  7923.  
  7924.     if ((code = krb5_timeofday(kcontext, &now))) {
  7925.         if (!status_only)
  7926.             debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
  7927.                    "",code);
  7928.         retval = -1;
  7929.         goto exit_k5_get_tkt;
  7930.     }
  7931.  
  7932.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  7933.         char *sname=NULL;
  7934.  
  7935.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  7936.         if (retval) {
  7937.             debug(F101,
  7938.           "ck_krb5_tkt_isvalid while unparsing server name","",retval);
  7939.             retval = -1;
  7940.             krb5_free_cred_contents(kcontext, &creds);
  7941.             goto exit_k5_get_tkt;
  7942.         }
  7943.  
  7944.         if ( !strcmp(sname,tktname) ) {
  7945.             /* we found the ticket we are looking for */
  7946.  
  7947.             /* We add a 5 minutes fudge factor to compensate for potential */
  7948.             /* clock skew errors between the KDC and K95's host OS         */
  7949.  
  7950.             retval = (creds.times.starttime &&
  7951.                        now >= (creds.times.starttime-300) &&
  7952.                        now < creds.times.endtime &&
  7953.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  7954.  
  7955. #ifdef CHECKADDRS
  7956.             if ( retval && krb5_checkaddrs ) {
  7957.                 /* if we think it is valid, then lets check the IP Addresses */
  7958.                 /* to make sure it is valid for our current connection.      */
  7959.                 /* Also make sure it's for the correct IP address */
  7960.         retval = krb5_os_localaddr(kcontext, &myAddrs);
  7961.                 if (retval) {
  7962.                     com_err(NULL, retval, "retrieving my IP address");
  7963.                     krb5_free_cred_contents(kcontext, &creds);
  7964.                     code = KRB5_CC_END;
  7965.                     retval = -1;
  7966.                     break;
  7967.                 }
  7968.  
  7969.          /* See if any of our addresses match any in cached credentials */
  7970.  
  7971.                 for (Addrfound=FALSE, p=myAddrs;
  7972.              (Addrfound==FALSE) && (*p);
  7973.              p++
  7974.              ) {
  7975.                     if (krb5_address_search(kcontext, *p, creds.addresses)) {
  7976.             Addrfound = TRUE;
  7977.                     }
  7978.                 }
  7979.                 krb5_free_addresses(k5_context, myAddrs);
  7980.  
  7981.                 if (Addrfound) {
  7982.                     krb5_free_cred_contents(kcontext, &creds);
  7983.                     code = KRB5_CC_END;
  7984.                     retval = 1;
  7985.                     break;
  7986.                 } else {
  7987.                     krb5_free_cred_contents(kcontext, &creds);
  7988.                     code = KRB5_CC_END;
  7989.                     retval = 0;
  7990.                     break;
  7991.                 }
  7992.             }
  7993. #endif /* CHECKADDRS */
  7994.  
  7995.             krb5_free_cred_contents(kcontext, &creds);
  7996.             code = KRB5_CC_END;
  7997.             break;
  7998.         }
  7999.     krb5_free_cred_contents(kcontext, &creds);
  8000.     }
  8001.  
  8002.     if (code == KRB5_CC_END) {
  8003.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  8004.             debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
  8005.                    "",code);
  8006.             retval = -1;
  8007.             goto exit_k5_get_tkt;
  8008.     }
  8009.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  8010.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8011.             debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
  8012.                    "",code);
  8013.             retval = -1;
  8014.             goto exit_k5_get_tkt;
  8015.     }
  8016.     } else {
  8017.         debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
  8018.         retval = -1;
  8019.         goto exit_k5_get_tkt;
  8020.     }
  8021.  
  8022.   exit_k5_get_tkt:
  8023.     krb5_free_principal(kcontext,princ);
  8024.     krb5_free_unparsed_name(kcontext,defname);
  8025.     krb5_cc_close(kcontext,cache);
  8026.     krb5_free_context(kcontext);
  8027.     return(retval);
  8028. #else /* KRB5 */
  8029.     return(-1);
  8030. #endif /* KRB5 */
  8031. }
  8032.  
  8033. int
  8034. #ifdef CK_ANSIC
  8035. ck_krb5_is_tgt_valid(VOID)
  8036. #else
  8037. ck_krb5_is_tgt_valid()
  8038. #endif
  8039. {
  8040. #ifdef KRB5
  8041.     char tgt[256];
  8042.     char * s;
  8043.     int rc = 0;
  8044.  
  8045.     s = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  8046.     sprintf(tgt,"krbtgt/%s@%s",s,s);
  8047.     rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
  8048.     debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
  8049.     return(rc>0);
  8050. #else /* KRB5 */
  8051.     return(0);
  8052. #endif /* KRB5 */
  8053. }
  8054.  
  8055. int
  8056. #ifdef CK_ANSIC
  8057. ck_krb5_tkt_time(char * cc_name, char * tktname)
  8058. #else
  8059. ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
  8060. #endif
  8061. {
  8062. #ifdef KRB5
  8063.     krb5_context kcontext;
  8064.     krb5_error_code retval;
  8065.     krb5_ccache cache = NULL;
  8066.     krb5_cc_cursor cur;
  8067.     krb5_creds creds;
  8068.     krb5_principal princ=NULL;
  8069.     krb5_flags flags=0;
  8070.     krb5_error_code code=0;
  8071.  
  8072.     if ( !ck_krb5_is_installed() )
  8073.         return(-1);
  8074.  
  8075.     retval = krb5_init_context(&kcontext);
  8076.     if (retval) {
  8077.         debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
  8078.         return(-1);
  8079.     }
  8080.  
  8081.     code = k5_get_ccache(kcontext,&cache,cc_name);
  8082.     if (code != 0) {
  8083.         debug(F111,"ck_krb5_tkt_time while getting ccache",
  8084.                error_message(code),code);
  8085.         retval = -1;
  8086.         goto exit_k5_get_tkt;
  8087.     }
  8088.  
  8089.     flags = 0;                /* turns off OPENCLOSE mode */
  8090.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8091.     if (code == ENOENT) {
  8092.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  8093.                    krb5_cc_get_name(kcontext, cache),code);
  8094.     } else {
  8095.             debug(F111,
  8096.          "ck_krb5_list_creds while setting cache flags (ticket cache)",
  8097.                   krb5_cc_get_name(kcontext, cache),code);
  8098.     }
  8099.         retval = -1;
  8100.         goto exit_k5_get_tkt;
  8101.     }
  8102.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  8103.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  8104.                "",code);
  8105.         retval = -1;
  8106.         goto exit_k5_get_tkt;
  8107.     }
  8108.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  8109.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  8110.                "",code);
  8111.         retval = -1;
  8112.         goto exit_k5_get_tkt;
  8113.     }
  8114.  
  8115.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  8116.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  8117.                "",code);
  8118.         retval = -1;
  8119.         goto exit_k5_get_tkt;
  8120.     }
  8121.  
  8122.     if ((code = krb5_timeofday(kcontext, &now))) {
  8123.         if (!status_only)
  8124.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  8125.                    "",code);
  8126.         krb5_free_context(kcontext);
  8127.         return(-1);
  8128.     }
  8129.  
  8130.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  8131.         char *sname=NULL;
  8132.  
  8133.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  8134.         if (retval) {
  8135.             debug(F101,
  8136.           "ck_krb5_list_creds while unparsing server name","",retval);
  8137.             retval = -1;
  8138.             krb5_free_cred_contents(kcontext, &creds);
  8139.             goto exit_k5_get_tkt;
  8140.         }
  8141.  
  8142.         if ( !strcmp(sname,tktname) ) {
  8143.             /* we found the ticket we are looking for */
  8144.             int valid = (creds.times.starttime &&
  8145.                        now > creds.times.starttime &&
  8146.                        now < creds.times.endtime &&
  8147.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  8148.             if ( valid ) {
  8149.                 retval = creds.times.endtime - now;
  8150.             }
  8151.             else
  8152.                 retval = 0;
  8153.             krb5_free_cred_contents(kcontext, &creds);
  8154.             code = KRB5_CC_END;
  8155.             break;
  8156.         }
  8157.     krb5_free_cred_contents(kcontext, &creds);
  8158.     }
  8159.  
  8160.     if (code == KRB5_CC_END) {
  8161.     if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  8162.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  8163.                    "",code);
  8164.             retval = -1;
  8165.             goto exit_k5_get_tkt;
  8166.     }
  8167.     flags = KRB5_TC_OPENCLOSE;    /* turns on OPENCLOSE mode */
  8168.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  8169.             debug(F101,"ck_krb5_list_creds while closing ccache",
  8170.                    "",code);
  8171.             retval = -1;
  8172.             goto exit_k5_get_tkt;
  8173.     }
  8174.     } else {
  8175.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  8176.         retval = -1;
  8177.         goto exit_k5_get_tkt;
  8178.     }
  8179.  
  8180.   exit_k5_get_tkt:
  8181.     krb5_free_principal(kcontext,princ);
  8182.     krb5_free_unparsed_name(kcontext,defname);
  8183.     krb5_cc_close(kcontext,cache);
  8184.     krb5_free_context(kcontext);
  8185.     return(retval);
  8186. #else /* KRB5 */
  8187.     return(-1);
  8188. #endif /* KRB5 */
  8189. }
  8190.  
  8191. char *
  8192. #ifdef CK_ANSIC
  8193. ck_krb5_get_cc_name(void)
  8194. #else
  8195. ck_krb5_get_cc_name()
  8196. #endif
  8197. {
  8198. #ifdef KRB5
  8199.     static char cc_name[CKMAXPATH+1]="";
  8200.     krb5_context kcontext = NULL;
  8201.     krb5_ccache ccache = NULL;
  8202.     krb5_error_code code;
  8203.     char * p=NULL;
  8204.  
  8205.     cc_name[0] = '\0';
  8206.  
  8207.     if ( !ck_krb5_is_installed() )
  8208.         return(cc_name);
  8209.  
  8210.     p = getenv("KRB5CCNAME");
  8211.     if ( !p ) {
  8212.         code = krb5_init_context(&kcontext);
  8213.         if (code) {
  8214.             com_err("ck_krb5_get_cc_name",code,"while init_context");
  8215.             return(cc_name);
  8216.         }
  8217.         if ((code = krb5_cc_default(kcontext, &ccache))) {
  8218.             com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
  8219.             goto exit_k5_get_cc;
  8220.         }
  8221.  
  8222.         sprintf(cc_name,"%s:%s",krb5_cc_get_type(kcontext,ccache),
  8223.                  krb5_cc_get_name(kcontext,ccache));
  8224.     } else {
  8225.         ckstrncpy(cc_name,p,CKMAXPATH);
  8226.     }
  8227.  
  8228.     if ( !strncmp("FILE:",cc_name,5) ) {
  8229.         for ( p=cc_name; *p ; p++ )
  8230.             if ( *p == '\\' ) *p = '/';
  8231.     }
  8232.  
  8233.   exit_k5_get_cc:
  8234.     if ( ccache )
  8235.         krb5_cc_close(kcontext,ccache);
  8236.     if ( kcontext )
  8237.         krb5_free_context(kcontext);
  8238.     return(cc_name);
  8239. #else /* KRB5 */
  8240.     return("");
  8241. #endif /* KRB5 */
  8242. }
  8243.  
  8244. char *
  8245. #ifdef CK_ANSIC
  8246. ck_krb5_getrealm(char * cc_name)
  8247. #else
  8248. ck_krb5_getrealm(cc_name) char * cc_name;
  8249. #endif
  8250. {
  8251. #ifdef KRB5
  8252.     static char realm[256]="";
  8253.     krb5_context kcontext;
  8254.     krb5_ccache ccache = NULL;
  8255.     krb5_error_code code;
  8256.     krb5_principal me;
  8257.  
  8258.     realm[0] = '\0';
  8259.  
  8260.     if ( !ck_krb5_is_installed() )
  8261.         return(realm);
  8262.  
  8263.     code = krb5_init_context(&kcontext);
  8264.     if (code) {
  8265.         return(realm);
  8266.     }
  8267.  
  8268.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  8269.     if (code != 0) {
  8270.         goto exit_k5_getrealm;
  8271.     }
  8272.  
  8273.     if ((code = krb5_parse_name(kcontext, "foo", &me))) {
  8274.         goto exit_k5_getrealm;
  8275.     }
  8276.     memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  8277.             krb5_princ_realm(kcontext, me)->length);
  8278.     realm[krb5_princ_realm(kcontext, me)->length]='\0';
  8279.  
  8280.   exit_k5_getrealm:
  8281.     if ( ccache )
  8282.         krb5_cc_close(kcontext,ccache);
  8283.     if (kcontext)
  8284.         krb5_free_context(kcontext);
  8285.     return(realm);
  8286. #else /* KRB5 */
  8287.     return("");
  8288. #endif /* KRB5 */
  8289. }
  8290.  
  8291. char *
  8292. #ifdef CK_ANSIC
  8293. ck_krb5_getprincipal(char * cc_name)
  8294. #else
  8295. ck_krb5_getprincipal(cc_name) char * cc_name;
  8296. #endif
  8297. {
  8298. #ifdef KRB5
  8299.     static char principal[UIDBUFLEN+1]="";
  8300.     krb5_context kcontext;
  8301.     krb5_ccache ccache = NULL;
  8302.     krb5_error_code code;
  8303.     krb5_principal me;
  8304.     char * p=NULL;
  8305.     int i;
  8306.  
  8307.     principal[0] = '\0';
  8308.  
  8309.     if ( !ck_krb5_is_installed() )
  8310.         return(principal);
  8311.  
  8312.     code = krb5_init_context(&kcontext);
  8313.     if (code) {
  8314.         return(principal);
  8315.     }
  8316.  
  8317.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  8318.     if (code != 0) {
  8319.         goto exit_k5_getprincipal;
  8320.     }
  8321.  
  8322.     if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
  8323.         goto exit_k5_getprincipal;
  8324.     }
  8325.  
  8326.     if ((code = krb5_unparse_name (kcontext, me, &p))) {
  8327.         krb5_free_principal(kcontext,me);
  8328.         goto exit_k5_getprincipal;
  8329.     }
  8330.  
  8331.     ckstrncpy(principal,p,UIDBUFLEN);
  8332.     i = ckindex("@",principal,0,0,0);
  8333.     if (i)
  8334.       principal[i-1] = '\0';
  8335.  
  8336.     krb5_free_unparsed_name(kcontext,p);
  8337.  
  8338.   exit_k5_getprincipal:
  8339.     if ( ccache )
  8340.         krb5_cc_close(kcontext,ccache);
  8341.     if (kcontext)
  8342.         krb5_free_context(kcontext);
  8343.     return(principal);
  8344. #else /* KRB5 */
  8345.     return("");
  8346. #endif /* KRB5 */
  8347. }
  8348.  
  8349. #ifndef CRYPT_DLL
  8350. int
  8351. ck_get_crypt_table(struct keytab ** pTable, int * pN)
  8352. {
  8353. #ifdef CK_ENCRYPTION
  8354.     return(get_crypt_table(pTable, pN));
  8355. #else /* ENCRYPTION */
  8356.     int i=0;
  8357. #ifndef OS2
  8358.     char * tmpstring = NULL;
  8359. #endif /* OS2 */
  8360.  
  8361.     if ( *pTable )
  8362.     {
  8363.         for ( i=0 ; i < *pN ; i++ )
  8364.             free( (*pTable)[i].kwd ) ;
  8365.         free ( *pTable )  ;
  8366.     }
  8367.     *pTable = NULL;
  8368.     *pN = 0;
  8369.  
  8370.     *pTable = malloc( sizeof(struct keytab) * 2 ) ;
  8371.     if ( !(*pTable) )
  8372.         return(0);
  8373.  
  8374. #ifdef OS2
  8375.     (*pTable)[0].kwd =strdup("automatic");
  8376. #else /* OS2 */
  8377.     makestr(&tmpstring,"automatic");
  8378.     (*pTable)[0].kwd = tmpstring;
  8379.     tmpstring = NULL;
  8380. #endif /* OS2 */
  8381.     (*pTable)[0].kwval = ENCTYPE_ANY;
  8382.     (*pTable)[0].flgs = 0;
  8383. #ifdef OS2
  8384.     (*pTable)[1].kwd =strdup("none");
  8385. #else /* OS2 */
  8386.     makestr(&tmpstring,"none");
  8387.     (*pTable)[1].kwd = tmpstring;
  8388.     tmpstring = NULL;
  8389. #endif /* OS2 */
  8390.     (*pTable)[1].kwval = 999;
  8391.     (*pTable)[1].flgs = 0;
  8392.     (*pN) = 2;
  8393.  
  8394.     return(2);
  8395. #endif /* ENCRYPTION */
  8396. }
  8397.  
  8398. VOID
  8399. ck_encrypt_send_support()
  8400. {
  8401. #ifdef CK_ENCRYPTION
  8402.     encrypt_send_support();
  8403. #endif /* ENCRYPTION */
  8404. }
  8405. #endif /* CRYPT_DLL */
  8406.  
  8407. /*
  8408.  *
  8409.  * Kstream
  8410.  *
  8411.  * Emulates the kstream package in Kerberos 4
  8412.  *
  8413.  */
  8414.  
  8415. int
  8416. kstream_destroy()
  8417. {
  8418.     if (g_kstream != NULL) {
  8419.         auth_destroy();                       /* Destroy authorizing */
  8420.         free(g_kstream);
  8421.         g_kstream=NULL;
  8422.     }
  8423.     return 0;
  8424. }
  8425.  
  8426. VOID
  8427. #ifdef CK_ANSIC
  8428. kstream_set_buffer_mode(int mode)
  8429. #else
  8430. kstream_set_buffer_mode(mode) int mode;
  8431. #endif
  8432. {
  8433. }
  8434.  
  8435.  
  8436. int
  8437. #ifdef CK_ANSIC
  8438. kstream_create_from_fd(int fd,
  8439.                const struct kstream_crypt_ctl_block *ctl,
  8440.                kstream_ptr data)
  8441. #else
  8442. kstream_create_from_fd(fd,ctl,data)
  8443.     int fd; const struct kstream_crypt_ctl_block *ctl; kstream_ptr data;
  8444. #endif
  8445. {
  8446.     int n;
  8447.  
  8448.     g_kstream = malloc(sizeof(struct kstream_int));
  8449.     if (g_kstream == NULL)
  8450.         return 0;
  8451.  
  8452.     g_kstream->fd = fd;
  8453.  
  8454.     n = auth_init(g_kstream);                   /* Initialize authorizing */
  8455.     if (n) {
  8456.         free(g_kstream);
  8457.         g_kstream = NULL;
  8458.         return 0;
  8459.     }
  8460.  
  8461.     g_kstream->encrypt = NULL;
  8462.     g_kstream->decrypt = NULL;
  8463.     g_kstream->encrypt_type = ENCTYPE_ANY;
  8464.     g_kstream->decrypt_type = ENCTYPE_ANY;
  8465.     return 1;
  8466. }
  8467.  
  8468. #ifdef RLOGCODE
  8469. #ifdef CK_KERBEROS
  8470.  
  8471. int
  8472. #ifdef CK_ANSIC
  8473. ck_krb_rlogin(CHAR * hostname, int port,
  8474.                CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
  8475.                struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
  8476.                int kversion, int encrypt_flag)
  8477. #else /* CK_ANSIC */
  8478. ck_krb_rlogin(hostname, port,
  8479.                localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
  8480.     CHAR * hostname; int port;
  8481.     CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
  8482.     struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
  8483.     int kversion; int encrypt_flag;
  8484. #endif /* CK_ANSIC */
  8485. {
  8486.     unsigned long status;
  8487.     char * realm=NULL;
  8488.     extern int ttyfd;
  8489.     int c;
  8490.     long msglen;
  8491.  
  8492.     debug(F111,"ck_krb_rlogin",hostname,port);
  8493.  
  8494.     if ( kversion == 4 && !ck_krb4_is_installed() ) {
  8495.         printf("?Kerberos 4 is not installed\r\n");
  8496.         return(-1);
  8497.     } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
  8498.         printf("?Kerberos 5 is not installed\r\n");
  8499.         return(-1);
  8500.     }
  8501.  
  8502.     if ( encrypt_flag && !ck_crypt_is_installed() ) {
  8503.         printf("?Encryption is not installed\r\n");
  8504.         return(-1);
  8505.     }
  8506.  
  8507.     if ( kversion == 5 ) {
  8508. #ifdef KRB5
  8509.         krb5_flags authopts=0;
  8510.         krb5_ccache ccache=NULL;
  8511.         char *cksumbuf=NULL;
  8512.         char *service=NULL;
  8513.         krb5_data cksumdat;
  8514.         krb5_creds *get_cred = 0;
  8515.         krb5_error_code status;
  8516.         krb5_error    *error = 0;
  8517.         krb5_ap_rep_enc_part *rep_ret = NULL;
  8518.         krb5_data outbuf;
  8519.         krb5_auth_context auth_context = NULL;
  8520.         int rc;
  8521.         krb5_int32 seqno=0;
  8522.         krb5_int32 server_seqno=0;
  8523.         char ** realmlist=NULL;
  8524.  
  8525.         debug(F100,"ck_krb_rlogin version 5","",0);
  8526.  
  8527.         if ((cksumbuf = malloc(strlen(term_speed)+strlen(remoteuser)+64)) == 0)
  8528.       {
  8529.           printf("Unable to allocate memory for checksum buffer.\r\n");
  8530.           return(-1);
  8531.       }
  8532.  
  8533.         sprintf(cksumbuf, "%u:", (unsigned short) ntohs(port));
  8534.         strcat(cksumbuf, term_speed);
  8535.         strcat(cksumbuf, remoteuser);
  8536.         cksumdat.data = cksumbuf;
  8537.         cksumdat.length = strlen(cksumbuf);
  8538.  
  8539.         status = krb5_init_context(&k5_context);
  8540.         if (status) {
  8541.             return(-1);
  8542.         }
  8543.  
  8544.         desinbuf.data = des_inbuf;
  8545.         desoutbuf.data = des_outpkt+4;    /* Set up des buffers */
  8546.  
  8547.         authopts = AP_OPTS_MUTUAL_REQUIRED;
  8548.  
  8549.         rc = k5_get_ccache(k5_context,&ccache,NULL);
  8550.         if (rc != 0) {
  8551.             com_err(NULL, rc, "while getting ccache.");
  8552.             return(0);
  8553.         }
  8554.  
  8555.         service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
  8556.  
  8557.         if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
  8558.             printf("kcmd: no memory\r\n");
  8559.             return(-1);
  8560.         }
  8561.         status = krb5_sname_to_principal(k5_context, hostname, service,
  8562.                                           KRB5_NT_SRV_HST, &get_cred->server);
  8563.         if (status) {
  8564.         printf("kcmd: krb5_sname_to_principal failed: %s\r\n",
  8565.                      error_message(status));
  8566.         return(-1);
  8567.         }
  8568.  
  8569.         krb5_get_host_realm(k5_context,hostname,&realmlist);
  8570.         if (realmlist && realmlist[0]) {
  8571.             makestr(&realm,realmlist[0]);
  8572.             krb5_free_host_realm(k5_context,realmlist);
  8573.             realmlist = NULL;
  8574.         }
  8575.         if (!realm || !realm[0] )
  8576.             realm = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  8577.         if (realm && *realm) {
  8578.             free(krb5_princ_realm(k5_context,get_cred->server)->data);
  8579.             krb5_princ_set_realm_length(k5_context,
  8580.                     get_cred->server,
  8581.                     strlen(realm)
  8582.                     );
  8583.             krb5_princ_set_realm_data(k5_context,
  8584.                       get_cred->server,
  8585.                       strdup(realm)
  8586.                       );
  8587.         }
  8588.  
  8589.         ttoc(0);
  8590.  
  8591.         if (status = krb5_cc_get_principal(k5_context,
  8592.                        ccache,
  8593.                        &get_cred->client)
  8594.         ) {
  8595.             (void) krb5_cc_close(k5_context, ccache);
  8596.             krb5_free_creds(k5_context, get_cred);
  8597.             goto bad2;
  8598.         }
  8599.  
  8600.         /* Get ticket from credentials cache or kdc */
  8601.         status = krb5_get_credentials(k5_context,
  8602.                       0,
  8603.                       ccache,
  8604.                       get_cred,
  8605.                       &ret_cred
  8606.                       );
  8607.         krb5_free_creds(k5_context, get_cred);
  8608.         get_cred = NULL;
  8609.         (void) krb5_cc_close(k5_context, ccache);
  8610.  
  8611.         if (status)
  8612.             goto bad2;
  8613.  
  8614.         if (krb5_auth_con_init(k5_context, &auth_context))
  8615.             goto bad2;
  8616.  
  8617.         if (krb5_auth_con_setflags(k5_context, auth_context,
  8618.                                     KRB5_AUTH_CONTEXT_RET_TIME))
  8619.             goto bad2;
  8620.  
  8621.         /* Only need local address for mk_cred() to send to krlogind */
  8622.         if (status = krb5_auth_con_genaddrs(k5_context,
  8623.                         auth_context,
  8624.                         ttyfd,
  8625.                 KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
  8626.                         )
  8627.         )
  8628.             goto bad2;
  8629.  
  8630.         /* call Kerberos library routine to obtain an authenticator,
  8631.            pass it over the socket to the server, and obtain mutual
  8632.            authentication.
  8633.          */
  8634.         status = krb5_sendauth(k5_context,
  8635.                    &auth_context,
  8636.                    (krb5_pointer) &ttyfd,
  8637.                    "KCMDV0.1",
  8638.                    ret_cred->client,
  8639.                    ret_cred->server,
  8640.                                 authopts,
  8641.                    &cksumdat,
  8642.                    ret_cred,
  8643.                    0,
  8644.                    &error,
  8645.                    &rep_ret,
  8646.                    NULL
  8647.                    );
  8648.         free(cksumdat.data);
  8649.  
  8650.         if (status) {
  8651.         printf("Couldn't authenticate to server: %s\r\n",
  8652.                      error_message(status));
  8653.             if (error) {
  8654.                 printf("Server returned error code %d (%s)\r\n",
  8655.                         error->error,
  8656.                         error_message(ERROR_TABLE_BASE_krb5 + error->error));
  8657.                 if (error->text.length) {
  8658.                     printf("Error text sent from server: %s\r\n",
  8659.                              error->text.data);
  8660.                 }
  8661.                 krb5_free_error(k5_context, error);
  8662.                 error = 0;
  8663.             }
  8664.             goto bad2;
  8665.         }
  8666.  
  8667.         if (rep_ret) {
  8668.             server_seqno = rep_ret->seq_number;
  8669.             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
  8670.         }
  8671.  
  8672.         (void) ttol(remoteuser, strlen(remoteuser)+1);
  8673.         (void) ttol(term_speed, strlen(term_speed)+1);
  8674.         (void) ttol(localuser, strlen(localuser)+1);
  8675.  
  8676.         if (forward_flag) {   /* Forward credentials (global) */
  8677.             if (status = krb5_fwd_tgt_creds( k5_context,
  8678.                                              auth_context,
  8679.                                              hostname,
  8680.                                              ret_cred->client,
  8681.                                              ret_cred->server,
  8682.                                              0,
  8683.                                              (forwardable_flag ?
  8684.                                                OPTS_FORWARDABLE_CREDS :
  8685.                                                0),
  8686.                                              &outbuf
  8687.                                              )
  8688.                  )
  8689.             {
  8690.                 printf("Error forwarding credentials: %s\r\n",
  8691.                          error_message(status));
  8692.                 goto bad2;
  8693.             }
  8694.  
  8695.             /* Send forwarded credentials */
  8696. #ifdef COMMENT
  8697.             if (status = krb5_write_message(k5_context,
  8698.                         (krb5_pointer)&ttyfd,
  8699.                         &outbuf
  8700.                         )
  8701.         )
  8702.                 goto bad2;
  8703. #else /* COMMENT */
  8704.             msglen = htonl(outbuf.length);
  8705.             if (ttol((CHAR *)&msglen,4) != 4) {
  8706.                 status = -1;
  8707.                 goto bad2;
  8708.             }
  8709.             if ( outbuf.length ) {
  8710.                 if (ttol(outbuf.data,outbuf.length) != outbuf.length) {
  8711.                     status = -1;
  8712.                     goto bad2;
  8713.                 }
  8714.             }
  8715. #endif /* COMMENT */
  8716.         }
  8717.         else { /* Dummy write to signal no forwarding */
  8718. #ifdef COMMENT
  8719.             outbuf.length = 0;
  8720.             if (status = krb5_write_message(k5_context,
  8721.                         (krb5_pointer)&ttyfd,
  8722.                         &outbuf
  8723.                         )
  8724.         )
  8725.                 goto bad2;
  8726. #else /* COMMENT */
  8727.             msglen = htonl(0);
  8728.             if (ttol((CHAR *)&msglen,4) != 4) {
  8729.                 status = -1;
  8730.                 goto bad2;
  8731.             }
  8732. #endif /* COMMENT */
  8733.         }
  8734.  
  8735.         if ((c = ttinc(0)) < 0) {
  8736.             if (c==-1) {
  8737.                 perror(hostname);
  8738.             } else {
  8739.                 printf("kcmd: bad connection with remote host\r\n");
  8740.             }
  8741.             status = -1;
  8742.             goto bad2;
  8743.         }
  8744.         if (c != 0) {
  8745.             while ((c = ttinc(1)) >= 0) {
  8746.                 (void) printf("%c",c);
  8747.                 if (c == '\n')
  8748.                     break;
  8749.             }
  8750.             status = -1;
  8751.             goto bad2;
  8752.         }
  8753.  
  8754. #ifdef MIT_CURRENT
  8755.         /* This code comes from the new MIT krb-current sources which is not */
  8756.         /* supported in the krb-1.0.5 distribution upon which all of the     */
  8757.         /* shipping libraries are based.                                     */
  8758.  
  8759.         if ( status == 0 ) {        /* success */
  8760.             krb5_boolean similar;
  8761.  
  8762.             rcmd_stream_init_krb5(&ret_cred->keyblock, encrypt_flag, 1);
  8763.             if (status = krb5_c_enctype_compare( k5_context,
  8764.                                                  ENCTYPE_DES_CBC_CRC,
  8765.                                                  ret_cred->keyblock.enctype,
  8766.                                                  &similar)) {
  8767.                 krb5_free_creds(k5_context, ret_cred);
  8768.                 ret_cred = NULL;
  8769.                 return(-1);
  8770.             }
  8771.  
  8772.             /* what is do_inband for? */
  8773.             if (!similar) {
  8774.                 do_inband = 1;
  8775.             }
  8776.         }
  8777. #else /* MIT_CURRENT */
  8778.         if ( status ) {
  8779.             /* should check for KDC_PR_UNKNOWN, NO_TKT_FILE here -- XXX */
  8780.             if (status != -1)
  8781.                 printf("[e]klogin to host %s failed - %s\r\n",hostname,
  8782.                          error_message(status));
  8783.             goto bad2;
  8784.         }
  8785.  
  8786.         if ( encrypt_flag ) {
  8787.             /* if we are encrypting we need to setup the encryption */
  8788.             /* routines.                                            */
  8789.             /* setup eblock for des_read and write */
  8790.             krb5_use_enctype(k5_context, &eblock,ret_cred->keyblock.enctype);
  8791.             if (status = krb5_process_key(k5_context,
  8792.                                            &eblock,
  8793.                                            &ret_cred->keyblock
  8794.                                            )
  8795.                  ) {
  8796.                 printf("Cannot process session key : %s.\r\n",
  8797.                          error_message(status)
  8798.                          );
  8799.                 goto bad2;
  8800.             }
  8801.             rlog_encrypt = 1;
  8802.         }
  8803.  
  8804. #endif /* MIT_CURRENT */
  8805.         return (0);     /* success */
  8806.  
  8807.       bad2:
  8808.       bad:
  8809.  
  8810.         if (ret_cred) {
  8811.             krb5_free_creds(k5_context, ret_cred);
  8812.             ret_cred = NULL;
  8813.         }
  8814.         return (status);
  8815. #else /* KRB5 */
  8816.         return(-1);
  8817. #endif /* KRB5 */
  8818.     } else if (kversion == 4) {
  8819. #ifdef KRB4
  8820.         debug(F100,"ck_krb_rlogin version 4","",0);
  8821.  
  8822.         realm = (char *)krb_realmofhost(szHostName);
  8823.         if ((realm == NULL) || (realm[0] == '\0')) {
  8824.             realm = krb4_d_realm;
  8825.         }
  8826.  
  8827.         ttoc(0);        /* write a NUL */
  8828.  
  8829.         status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
  8830.                                ttyfd,
  8831.                                &k4_auth,
  8832.                                krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  8833.                                hostname,
  8834.                                realm,
  8835.                                (unsigned long) getpid(),
  8836.                                &k4_msg_data,
  8837.                                (CREDENTIALS *)&cred,
  8838. #ifdef CK_ENCRYPTION
  8839.                                &k4_sched,
  8840. #else /* ENCRYPTION */
  8841.                                NULL,
  8842. #endif /* ENCRYPTION */
  8843.                                l_addr,
  8844.                                r_addr,
  8845.                                "KCMDV0.1");
  8846.         debug(F111,"ck_krb_rlogin","krb_sendauth",status);
  8847.         if (status != KSUCCESS) {
  8848.             printf( "krb_sendauth failed: %s\r\n",
  8849.             krb_get_err_text_entry(status)
  8850.             );
  8851.             return(-1);
  8852.         }
  8853.         ttol(remoteuser,strlen(remoteuser)+1);
  8854.         ttol(term_speed,strlen(term_speed)+1);
  8855.  
  8856.       reread:
  8857.         if ((c = ttinc(0)) < 0) {
  8858.             printf("rcmd: bad connection with remote host\r\n");
  8859.             return(-1);
  8860.         }
  8861.         debug(F111,"ck_krb_rlogin","first byte",c);
  8862.  
  8863.         if (c != 0) {
  8864.             char *check = "ld.so: warning:";
  8865.             /* If rlogind was compiled on SunOS4, and it somehow
  8866.             got the shared library version numbers wrong, it
  8867.             may give an ld.so warning about an old version of a
  8868.             shared library.  Just ignore any such warning.
  8869.             Note that the warning is a characteristic of the
  8870.             server; we may not ourselves be running under
  8871.             SunOS4.  */
  8872.             if (c == 'l') {
  8873.                 char *p;
  8874.                 char cc;
  8875.  
  8876.                 p = &check[1];
  8877.                 while ((c = ttinc(0)) >= 0) {
  8878.                     if (*p == '\0') {
  8879.                         if (c == '\n')
  8880.                             break;
  8881.                     } else {
  8882.                         if (c != *p)
  8883.                             break;
  8884.                         ++p;
  8885.                     }
  8886.                 }
  8887.  
  8888.                 if (*p == '\0')
  8889.                     goto reread;
  8890.             }
  8891.  
  8892.             printf(check);
  8893.             while ((c = ttinc(1)) >= 0) {
  8894.                 printf("%c",c);
  8895.                 if (c == '\n')
  8896.                     break;
  8897.             }
  8898.             debug(F110,"ck_krb_rlogin","fatal error 1",0);
  8899.             return(-1);
  8900.         }
  8901.  
  8902. #ifdef CK_ENCRYPTION
  8903.         if ( encrypt_flag ) {
  8904.             /* if we are encrypting we need to setup the encryption */
  8905.             /* routines.                                            */
  8906.             des_key_sched(cred.session, k4_sched);
  8907.             rlog_encrypt = 1;
  8908.         }
  8909. #endif /* ENCRYPTION */
  8910. #else /* KRB4 */
  8911.         return(-1);
  8912. #endif /* KRB4 */
  8913.     }
  8914.     return(0); /* success */
  8915. }
  8916.  
  8917. #define SRAND    srand
  8918. #define RAND    rand
  8919. #define RAND_TYPE    int
  8920.  
  8921. static long
  8922. random_confounder(size, fillin)
  8923. size_t size;
  8924. char * fillin;
  8925. {
  8926.     static int seeded = 0;
  8927.     register unsigned char *real_fill;
  8928.     RAND_TYPE    rval;
  8929.  
  8930.     if (!seeded) {
  8931.     /* time() defined in 4.12.2.4, but returns a time_t, which is an
  8932.        "arithmetic type" (4.12.1) */
  8933.     rval = (RAND_TYPE) time(0);
  8934.     SRAND(rval);
  8935.     rval = RAND();
  8936.     rval ^= getpid();
  8937.     SRAND(rval);
  8938.     seeded = 1;
  8939.     }
  8940.  
  8941.     real_fill = (unsigned char *)fillin;
  8942.     while (size > 0) {
  8943.     rval = RAND();
  8944.     *real_fill = rval & 0xff;
  8945.     real_fill++;
  8946.     size--;
  8947.     if (size) {
  8948.         *real_fill = (rval >> 8) & 0xff;
  8949.         real_fill++;
  8950.         size--;
  8951.     }
  8952.     }
  8953.     return 0;
  8954. }
  8955.  
  8956. #ifdef KRB5
  8957. int
  8958. krb5_des_avail(fd)
  8959.     int fd;
  8960. {
  8961.     return(nstored);
  8962. }
  8963.  
  8964. int
  8965. krb5_des_read(fd, buf, len)
  8966.      int fd;
  8967.      register char *buf;
  8968.      int len;
  8969. {
  8970.     int nreturned = 0;
  8971.     long net_len,rd_len;
  8972.     int cc;
  8973.     unsigned char len_buf[4];
  8974.     krb5_error_code status;
  8975.     unsigned char c;
  8976.     int gotzero = 0;
  8977.  
  8978.     debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
  8979.     debug(F111,"krb5_des_read","len",len);
  8980.     if ( !rlog_encrypt ) {
  8981.         cc = krb5_net_read(k5_context, fd, buf, len);
  8982.         debug(F111,"krb5_des_read","chars read",cc);
  8983.         if ( cc < 0 )
  8984.             netclos();
  8985.         return(cc);
  8986.     }
  8987.  
  8988.     if (nstored >= len) {
  8989.         if ( buf ) {
  8990.             memcpy(buf, store_ptr, len);
  8991.             store_ptr += len;
  8992.             nstored -= len;
  8993.             return(len);
  8994.         } else
  8995.             return(0);
  8996.     } else if (nstored) {
  8997.         if ( buf ) {
  8998.             memcpy(buf, store_ptr, nstored);
  8999.             nreturned += nstored;
  9000.             buf += nstored;
  9001.             len -= nstored;
  9002.             nstored = 0;
  9003.         }
  9004.         else
  9005.             return(0);
  9006.     }
  9007.  
  9008.     /* See the comment in v4_des_read. */
  9009.     do {
  9010.         cc = krb5_net_read(k5_context, fd, &c, 1);
  9011.         /* we should check for non-blocking here, but we'd have
  9012.         to make it save partial reads as well. */
  9013.         if (cc <= 0) {
  9014.             return cc; /* read error */
  9015.         }
  9016.         if (cc == 1) {
  9017.             if (c == 0) gotzero = 1;
  9018.         }
  9019.     } while (!gotzero);
  9020.  
  9021.     if ((cc = krb5_net_read(k5_context, fd, &c, 1)) != 1) return 0;
  9022.     rd_len = c;
  9023.     if ((cc = krb5_net_read(k5_context, fd, &c, 1)) != 1) return 0;
  9024.     rd_len = (rd_len << 8) | c;
  9025.     if ((cc = krb5_net_read(k5_context, fd, &c, 1)) != 1) return 0;
  9026.     rd_len = (rd_len << 8) | c;
  9027.  
  9028.     net_len = krb5_encrypt_size(rd_len, eblock.crypto_entry);
  9029.     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
  9030.     /* preposterous length; assume out-of-sync; only
  9031.        recourse is to close connection, so return 0 */
  9032.     printf("Read size problem.\r\n");
  9033.     return(0);
  9034.     }
  9035.     if ((cc = krb5_net_read(k5_context,
  9036.                 fd,
  9037.                 desinbuf.data,
  9038.                 net_len)) != net_len )
  9039.     {
  9040.     /* pipe must have closed, return 0 */
  9041.     printf(    "Read error: length received %d != expected %d.\r\n",
  9042.         cc,
  9043.         net_len
  9044.         );
  9045.     return(0);
  9046.     }
  9047.     /* decrypt info */
  9048.     if ((status = krb5_decrypt(k5_context, desinbuf.data,
  9049.               (krb5_pointer) storage,
  9050.               net_len,
  9051.               &eblock, 0))) {
  9052.     printf("Cannot decrypt data from network: %s\r\n",
  9053.                  error_message(status));
  9054.     return(0);
  9055.     }
  9056.     store_ptr = storage;
  9057.     nstored = rd_len;
  9058.     if ( !buf ) {
  9059.         return(0);
  9060.     }
  9061.  
  9062.     if (nstored > len) {
  9063.     memcpy(buf, store_ptr, len);
  9064.     nreturned += len;
  9065.     store_ptr += len;
  9066.     nstored -= len;
  9067.     } else {
  9068.     memcpy(buf, store_ptr, nstored);
  9069.     nreturned += nstored;
  9070.     nstored = 0;
  9071.     }
  9072.     return(nreturned);
  9073. }
  9074.  
  9075.  
  9076.  
  9077. int
  9078. krb5_des_write(fd, buf, len)
  9079.      int fd;
  9080.      char *buf;
  9081.      int len;
  9082. {
  9083.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  9084.     int cc;
  9085.     krb5_error_code status;
  9086.  
  9087.     debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
  9088.     if ( !rlog_encrypt ) {
  9089.         cc = krb5_net_write(k5_context, fd, buf, len);
  9090.         debug(F111,"krb5_net_write","chars written",cc);
  9091.         return(cc != len ? -1 : len);
  9092.     }
  9093.  
  9094.     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
  9095.     if (desoutbuf.length > sizeof(des_outpkt)-4){
  9096.           printf("Write size problem.\r\n");
  9097.     return(-1);
  9098.     }
  9099.     if ((status = krb5_encrypt(k5_context, (krb5_pointer)buf,
  9100.               desoutbuf.data,
  9101.               len,
  9102.               &eblock,
  9103.               0))){
  9104.           printf("Write encrypt problem: %s.\r\n",
  9105.                  error_message(status));
  9106.     return(-1);
  9107.     }
  9108.  
  9109.     len_buf[0] = (len & 0xff000000) >> 24;
  9110.     len_buf[1] = (len & 0xff0000) >> 16;
  9111.     len_buf[2] = (len & 0xff00) >> 8;
  9112.     len_buf[3] = (len & 0xff);
  9113.  
  9114.     if (krb5_net_write(k5_context, fd, des_outpkt,desoutbuf.length+4)
  9115.          != desoutbuf.length+4){
  9116.         printf("Could not write out all data\r\n");
  9117.     return(-1);
  9118.     }
  9119.     else return(len);
  9120. }
  9121. #endif /* KRB5 */
  9122.  
  9123. #ifdef KRB4
  9124. /*
  9125.  * Note that the encrypted rlogin packets take the form of a four-byte
  9126.  * length followed by encrypted data.  On writing the data out, a significant
  9127.  * performance penalty is suffered (at least one RTT per character, two if we
  9128.  * are waiting for a shell to echo) by writing the data separately from the
  9129.  * length.  So, unlike the input buffer, which just contains the output
  9130.  * data, the output buffer represents the entire packet.
  9131.  */
  9132.  
  9133. int
  9134. krb4_des_avail(fd)
  9135.     int fd;
  9136. {
  9137.     return(nstored);
  9138. }
  9139.  
  9140. int
  9141. krb4_des_read(fd, buf, len)
  9142. int fd;
  9143. register char *buf;
  9144. int len;
  9145. {
  9146.     int nreturned = 0;
  9147.     unsigned long net_len, rd_len;
  9148.     int cc;
  9149.     unsigned char c;
  9150.     int gotzero = 0;
  9151.  
  9152.     debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
  9153.     debug(F111,"krb4_des_read","len",len);
  9154.     if ( !rlog_encrypt ) {
  9155.         cc = krb_net_read(fd, buf, len);
  9156.         debug(F111,"krb4_des_read","chars read",cc);
  9157.         if ( cc < 0 )
  9158.             netclos();
  9159.         return(cc);
  9160.     }
  9161.  
  9162.     if (nstored >= len) {
  9163.         if ( buf ) {
  9164.             debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
  9165.             memcpy(buf, store_ptr, len);
  9166.             store_ptr += len;
  9167.             nstored -= len;
  9168.             return(len);
  9169.         } else
  9170.             return(0);
  9171.     } else if (nstored) {
  9172.         if ( buf ) {
  9173.             debug(F111,"krb4_des_read (nstored)","nstored",nstored);
  9174.             memcpy(buf, store_ptr, nstored);
  9175.             nreturned += nstored;
  9176.             buf += nstored;
  9177.             len -= nstored;
  9178.             nstored = 0;
  9179.         } else
  9180.             return(0);
  9181.     }
  9182.  
  9183.     /* We're fetching the length which is MSB first, and the MSB
  9184.     has to be zero unless the client is sending more than 2^24
  9185.     (16M) bytes in a single write (which is why this code is in
  9186.     rlogin but not rcp or rsh.) The only reasons we'd get something
  9187.     other than zero are:
  9188.     -- corruption of the tcp stream (which will show up when
  9189.     everything else is out of sync too)
  9190.     -- un-caught Berkeley-style "pseudo out-of-band data" which
  9191.     happens any time the user hits ^C twice.
  9192.     The latter is *very* common, as shown by an 'rlogin -x -d'
  9193.     using the CNS V4 rlogin.         Mark EIchin 1/95
  9194.     */
  9195.     debug(F110,"krb4_des_read",
  9196.       "about to call krb_net_read() this will block",
  9197.       0
  9198.       );
  9199.     do {
  9200.         cc = krb_net_read(fd, &c, 1);
  9201.         debug(F111,"krb_net_read","chars read",cc);
  9202.         if (cc <= 0) {
  9203.             netclos();
  9204.             return(-1);
  9205.         }
  9206.         if (cc != 1) return 0; /* read error */
  9207.         if (cc == 1) {
  9208.             if (c == 0) gotzero = 1;
  9209.         }
  9210.     } while (!gotzero);
  9211.  
  9212.     debug(F110,"krb4_des_read","gotzero",0);
  9213.     cc = krb_net_read(fd, &c, 1);
  9214.     debug(F111,"krb_net_read","chars read",cc);
  9215.     if (cc < 0) {
  9216.         netclos();
  9217.         return(-1);
  9218.     } else if ( cc != 1 )
  9219.         return(0);
  9220.     net_len = c;
  9221.     cc = krb_net_read(fd, &c, 1);
  9222.     debug(F111,"krb_net_read","chars read",cc);
  9223.     if (cc < 0) {
  9224.         netclos();
  9225.         return(-1);
  9226.     } else if ( cc != 1 )
  9227.         return(0);
  9228.     net_len = (net_len << 8) | c;
  9229.     debug(F111,"krb_net_read","chars read",cc);
  9230.     cc = krb_net_read(fd, &c, 1);
  9231.     if (cc < 0) {
  9232.         netclos();
  9233.         return(-1);
  9234.     } else if ( cc != 1 )
  9235.         return(0);
  9236.     net_len = (net_len << 8) | c;
  9237.     debug(F111,"krb4_des_read","net_len",net_len);
  9238.  
  9239.     /* Note: net_len is unsigned */
  9240.     if (net_len > sizeof(des_inbuf)) {
  9241.         /* XXX preposterous length, probably out of sync.
  9242.         act as if pipe closed */
  9243.         return(0);
  9244.     }
  9245.     /* the writer tells us how much real data we are getting, but
  9246.     we need to read the pad bytes (8-byte boundary) */
  9247. #ifndef roundup
  9248. #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
  9249. #endif /* roundup */
  9250.     rd_len = roundup(net_len, 8);
  9251.     debug(F111,"krb4_des_read","rd_len",rd_len);
  9252.     cc = krb_net_read(fd, des_inbuf, rd_len);
  9253.     debug(F111,"krb_net_read","chars read",cc);
  9254.     if (cc < 0) {
  9255.         netclos();
  9256.         return(-1);
  9257.     } else if ( cc != rd_len )
  9258.         return(0);
  9259.  
  9260.     hexdump("krb4_des_read des_inbuf",des_inbuf,8);
  9261. #ifdef CK_ENCRYPTION
  9262. #ifdef NT
  9263.     (void) des_pcbc_encrypt(des_inbuf,
  9264.                              storage,
  9265.                              (net_len < 8) ? 8 : net_len,
  9266.                              k4_sched,
  9267.                              cred.session,
  9268.                              DECRYPT);
  9269. #else /* NT */
  9270.     (void) des_pcbc_encrypt((Block *)des_inbuf,
  9271.                              (Block *)storage,
  9272.                              (net_len < 8) ? 8 : net_len,
  9273.                              k4_sched,
  9274.                              &cred.session,
  9275.                              DECRYPT);
  9276. #endif /* NT */
  9277. #endif /* ENCRYPTION */
  9278.     hexdump("krb4_des_read storage",storage,8);
  9279.  
  9280.     /*
  9281.     * when the cleartext block is < 8 bytes, it is "right-justified"
  9282.     * in the block, so we need to adjust the pointer to the data
  9283.     */
  9284.     if (net_len < 8)
  9285.         store_ptr = storage + 8 - net_len;
  9286.     else
  9287.         store_ptr = storage;
  9288.     nstored = net_len;
  9289.  
  9290.     if ( !buf )
  9291.         return(0);
  9292.  
  9293.     if (nstored > len) {
  9294.         memcpy(buf, store_ptr, len);
  9295.         nreturned += len;
  9296.         store_ptr += len;
  9297.         nstored -= len;
  9298.     } else {
  9299.         memcpy(buf, store_ptr, nstored);
  9300.         nreturned += nstored;
  9301.         nstored = 0;
  9302.     }
  9303.  
  9304.     debug(F111,"krb_net_read","nreturned",nreturned);
  9305.     return(nreturned);
  9306. }
  9307.  
  9308. int
  9309. krb4_des_write(fd, buf, len)
  9310. int fd;
  9311. char *buf;
  9312. int len;
  9313. {
  9314.     static char garbage_buf[8];
  9315.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  9316.     int cc;
  9317.  
  9318.     debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
  9319.     if ( !rlog_encrypt ) {
  9320.         cc = krb_net_write(fd, buf, len);
  9321.         debug(F111,"krb_net_write","chars written",cc);
  9322.         return(cc);
  9323.     }
  9324.  
  9325.     /*
  9326.     * pcbc_encrypt outputs in 8-byte (64 bit) increments
  9327.     *
  9328.     * it zero-fills the cleartext to 8-byte padding,
  9329.     * so if we have cleartext of < 8 bytes, we want
  9330.     * to insert random garbage before it so that the ciphertext
  9331.     * differs for each transmission of the same cleartext.
  9332.     * if len < 8 - sizeof(long), sizeof(long) bytes of random
  9333.     * garbage should be sufficient; leave the rest as-is in the buffer.
  9334.     * if len > 8 - sizeof(long), just garbage fill the rest.
  9335.     */
  9336.     if (len < 8) {
  9337.         random_confounder(8 - len, garbage_buf);
  9338.         /* this "right-justifies" the data in the buffer */
  9339.         (void) memcpy(garbage_buf + 8 - len, buf, len);
  9340.     }
  9341.     if ( len < 8 )
  9342.         hexdump("krb4_des_write garbage_buf",garbage_buf,8);
  9343.     else
  9344.         hexdump("krb4_des_write buf",buf,8);
  9345. #ifdef CK_ENCRYPTION
  9346. #ifdef NT
  9347.     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
  9348.                              des_outpkt+4,
  9349.                              (len < 8) ? 8 : len,
  9350.                              k4_sched,
  9351.                              cred.session,
  9352.                              ENCRYPT);
  9353. #else /* NT */
  9354.     (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
  9355.                              (Block *)(des_outpkt+4),
  9356.                              (len < 8) ? 8 : len,
  9357.                              k4_sched,
  9358.                              &cred.session,
  9359.                              ENCRYPT);
  9360. #endif /* NT */
  9361. #endif /* ENCRYPTION */
  9362.     if ( len < 8 )
  9363.         hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
  9364.     else
  9365.         hexdump("krb4_des_write (post pcbc) buf",buf,8);
  9366.     hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
  9367.  
  9368.     /* tell the other end the real amount, but send an 8-byte padded
  9369.     packet */
  9370.     len_buf[0] = (len & 0xff000000) >> 24;
  9371.     len_buf[1] = (len & 0xff0000) >> 16;
  9372.     len_buf[2] = (len & 0xff00) >> 8;
  9373.     len_buf[3] = (len & 0xff);
  9374.     hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
  9375.     cc = krb_net_write(fd, des_outpkt, roundup(len,8)+4);
  9376.     debug(F111,"krb_net_write","chars written",cc);
  9377.     return(len);
  9378. }
  9379. #endif /* KRB4 */
  9380.  
  9381. #ifdef KRB524
  9382. /* The following functions are missing from the compatibility library */
  9383. const char *
  9384. krb_get_err_text_entry(r) int r;
  9385. {
  9386.     extern char krb_err_text[];
  9387.     return(krb_err_txt[r]);
  9388. }
  9389. #endif /* KRB524 */
  9390. #endif /* CK_KERBEROS */
  9391. #endif /* RLOGCODE */
  9392. #endif /* CK_AUTHENTICATION */
  9393.