ckuath.c
上传用户:dufan58
上传日期:2007-01-05
资源大小:3407k
文件大小:270k
源码类别:

通讯/手机编程

开发平台:

Windows_Unix

  1. #ifdef CK_ANSIC
  2. short_date(long   *dp)
  3. #else
  4. short_date(dp) long   *dp;
  5. #endif
  6. {
  7.     register char *cp;
  8.     extern char *ctime();
  9.     cp = ctime(dp) + 4;
  10.     cp[15] = '';
  11.     return (cp);
  12. }
  13. static VOID
  14. #ifdef CK_ANSIC
  15. printtime(time_t tv)
  16. #else
  17. printtime(tv) time_t tv;
  18. #endif
  19. {
  20.     char timestring[BUFSIZ];
  21.     char format[12];
  22.     char fill;
  23.     fill = ' ';
  24.     sprintf(format,"%%-%ds",timestamp_width);
  25.     if (!krb5_timestamp_to_sfstring((krb5_timestamp) tv,
  26.                                      timestring,
  27.                                      timestamp_width+1,
  28.      &fill)) {
  29.         printf(format,timestring);
  30.     }
  31.     else {
  32.         printf(format,short_date(&tv));
  33.     }
  34. }
  35. static void
  36. #ifdef CK_ANSIC
  37. one_addr(krb5_address *a)
  38. #else
  39. one_addr(a) krb5_address *a;
  40. #endif
  41. {
  42.     struct hostent *h;
  43.     extern tcp_rdns;
  44.     if ((a->addrtype == ADDRTYPE_INET) &&
  45.         (a->length == 4)) {
  46.         if (tcp_rdns != SET_OFF) {
  47.             h = gethostbyaddr(a->contents, 4, AF_INET);
  48.             if (h) {
  49.                 printf("%s (%d.%d.%d.%d)", h->h_name,
  50. a->contents[0], a->contents[1],
  51. a->contents[2], a->contents[3]);
  52.             }
  53.         }
  54.         if (tcp_rdns == SET_OFF || !h) {
  55.             printf("%d.%d.%d.%d", a->contents[0], a->contents[1],
  56.                    a->contents[2], a->contents[3]);
  57.         }
  58.     } else {
  59.         printf("unknown addr type %d", a->addrtype);
  60.     }
  61. }
  62. static VOID
  63. #ifdef CK_ANSIC
  64. show_credential(krb5_context kcontext, register krb5_creds * cred)
  65. #else
  66. show_credential(kcontext, cred)
  67.     krb5_context     kcontext;
  68.     register krb5_creds * cred;
  69. #endif
  70. {
  71.     krb5_error_code retval=0;
  72.     krb5_ticket *tkt=NULL;
  73.     char *name=NULL, *sname=NULL, *flags=NULL;
  74.     int extra_field = 0;
  75.     retval = krb5_unparse_name(kcontext, cred->client, &name);
  76.     if (retval) {
  77. debug(F101,"ck_krb5_list_creds while unparsing client name","",retval);
  78.         krb5_errno = retval;
  79.         makestr(&krb5_errmsg,error_message(krb5_errno));
  80. return;
  81.     }
  82.     retval = krb5_unparse_name(kcontext, cred->server, &sname);
  83.     if (retval) {
  84. debug(F101,"ck_krb5_list_creds while unparsing server name","",retval);
  85. free(name);
  86.         krb5_errno = retval;
  87.         makestr(&krb5_errmsg,error_message(krb5_errno));
  88. return;
  89.     }
  90.     if (!cred->times.starttime)
  91. cred->times.starttime = cred->times.authtime;
  92.     printtime(cred->times.starttime);
  93.     printf("  ");
  94.     if ( time(0) < cred->times.endtime )
  95.         printtime(cred->times.endtime);
  96.     else
  97.         printf("** expired ** ");
  98.     printf("  %srn", sname);
  99.     if (strcmp(name, defname)) {
  100.         printf("   for client %s", name);
  101.         extra_field++;
  102.     }
  103.     if (cred->times.renew_till) {
  104. if (!extra_field)
  105.             printf("   ");
  106. else
  107.             printf(", ");
  108. printf("renew until ");
  109.         printtime(cred->times.renew_till);
  110. extra_field += 2;
  111.     }
  112.     if (extra_field > 3) {
  113. printf("rn");
  114. extra_field = 0;
  115.     }
  116.     if (show_flags) {
  117. flags = flags_string(cred);
  118. if (flags && *flags) {
  119.     if (!extra_field)
  120. printf("   ");
  121.     else
  122. printf(", ");
  123.     printf("Flags: %s", flags);
  124.     extra_field++;
  125.         }
  126.     }
  127.     if (extra_field > 2) {
  128. printf("rn");
  129. extra_field = 0;
  130.     }
  131.     if (show_etype) {
  132. retval = decode_krb5_ticket(&cred->ticket, &tkt);
  133. if (!extra_field)
  134.     printf("   ");
  135. else
  136.     printf(", ");
  137. printf("Etype (skey, tkt): %s, %s ",
  138.        etype_string(cred->keyblock.enctype),
  139.        etype_string(tkt->enc_part.enctype));
  140. krb5_free_ticket(kcontext, tkt);
  141. extra_field++;
  142.     }
  143.     /* if any additional info was printed, extra_field is non-zero */
  144.     if (extra_field)
  145. printf("rn");
  146.     if ( show_addr ) {
  147.         if (!cred->addresses || !cred->addresses[0]) {
  148.             printf("tAddresses: (none)rn");
  149.         } else {
  150.             int i;
  151.             for (i=0; cred->addresses[i]; i++) {
  152. if (i)
  153.     printf("              ");
  154. else
  155.     printf("   Addresses: ");
  156.                 one_addr(cred->addresses[i]);
  157. printf("rn");
  158.             }
  159.         }
  160.     }
  161.     free(name);
  162.     free(sname);
  163.     krb5_errno = retval;
  164.     makestr(&krb5_errmsg,error_message(krb5_errno));
  165. }
  166. static VOID
  167. #ifdef CK_ANSIC
  168. fillit(int num, int c)
  169. #else
  170. fillit(num, c) int num; int c;
  171. #endif
  172. {
  173.     int i;
  174.     for (i=0; i<num; i++)
  175. printf("%c",c);
  176. }
  177. #endif /* KLIST */
  178. #endif /* KRB5 */
  179. #ifdef KRB4
  180. #define KDEBUG 1
  181. int k4debug = 0;                /* Kerberos 4 runtime debugging */
  182. #ifdef KINIT
  183. #define KRB_DEFAULT_LIFE 120 /* 10 hours in 5 minute intervals */
  184. #ifdef SNK4
  185. /* SNK4 is a hardware authentication system used to pre-authenticate    */
  186. /* a ticket getting ticket.  We do not support this code at the present */
  187. /* time in Kermit.                                                      */
  188. void
  189. get_input(s, size, stream)
  190. char *s;
  191. int size;
  192. FILE *stream;
  193. {
  194.     char *p;
  195.     if (fgets(s, size, stream) == NULL)
  196.         exit(1);
  197.     if ( (p = strchr(s, 'n')) != NULL)
  198.         *p = '';
  199. }
  200. #endif /* SNK4 */
  201. #ifdef COMMENT
  202. static char
  203. #ifdef CK_ANSIC
  204. hex_scan_nybble(char c)
  205. #else
  206. hex_scan_nybble(c) char c;
  207. #endif
  208. {
  209.     if (c >= '0' && c <= '9')
  210.         return c - '0';
  211.     if (c >= 'A' && c <= 'F')
  212.         return c - 'A' + 10;
  213.     if (c >= 'a' && c <= 'f')
  214.         return c - 'a' + 10;
  215.     return -1;
  216. }
  217. /* returns: NULL for ok, pointer to error string for bad input */
  218. static char*
  219. #ifdef CK_ANSIC
  220. hex_scan_four_bytes(char *out, char *in)
  221. #else
  222. hex_scan_four_bytes(out, in) char *out; char *in;
  223. #endif
  224. {
  225.     int i;
  226.     int c;
  227.     char c1;
  228.     for (i=0; i<8; i++) {
  229.         if(!in[i])
  230.             return "not enough input";
  231.         c = hex_scan_nybble(in[i]);
  232.         if(c<0)
  233.             return "invalid digit";
  234.         c1 = c;
  235.         i++;
  236.         if(!in[i])
  237.             return "not enough input";
  238.         c = hex_scan_nybble(in[i]);
  239.         if(c<0)
  240.             return "invalid digit";
  241.         *out++ = (c1 << 4) + c;
  242.     }
  243.     switch(in[i]) {
  244.     case 0:
  245.     case 'r':
  246.     case 'n':
  247.         return NULL;
  248.     default:
  249.         return "extra characters at end of input";
  250.     }
  251. }
  252. #endif /* COMMENT */
  253. /* ck_krb4_initTGT() returns 0 on success */
  254. int
  255. #ifdef CK_ANSIC
  256. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  257. #else
  258. ck_krb4_initTGT(op,init)
  259.     struct krb_op_data * op, struct krb4_init_data * init
  260. #endif
  261. {
  262.     char    aname[ANAME_SZ+1];
  263.     char    inst[INST_SZ+1];
  264.     char    realm[REALM_SZ+1];
  265.     char    *password=NULL;
  266.     char   *username = NULL;
  267.     char   *usernameptr=NULL;
  268.     int     iflag,      /* Instance */
  269.             rflag,      /* Realm */
  270.             vflag,      /* Verbose */
  271.             lflag,      /* Lifetime */
  272.             pflag,      /* Preauth */
  273.             lifetime=KRB_DEFAULT_LIFE,   /* Life Time */
  274.             k_errno;
  275.     register char *cp;
  276.     register i;
  277.     if ( !ck_krb4_is_installed() )
  278.         return(-1);
  279.     *inst = *realm = '';
  280.     iflag = rflag = vflag = lflag = pflag = 0;
  281.     vflag = init->verbose;
  282.     pflag = init->preauth;
  283.     if ( init->lifetime ) {
  284.         lifetime = init->lifetime<5?1:init->lifetime/5;
  285.         if ( lifetime > 255 ) lifetime = 255;
  286.     }
  287.     else
  288.         lifetime = KRB_DEFAULT_LIFE;
  289.     username = init->principal;
  290.     password = init->password;
  291.     if (username && username[0] &&
  292. (k_errno = kname_parse(aname, inst, realm, username))
  293. != AUTH_SUCCESS) {
  294.         krb4_errno = k_errno;
  295.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  296. printf("%srn", krb_get_err_text_entry(k_errno));
  297. iflag = rflag = 1;
  298. username = NULL;
  299.     }
  300.     if ( init->realm ) {
  301.         ckstrncpy(realm,init->realm,REALM_SZ);
  302.     }
  303.     if ( init->instance ) {
  304.         ckstrncpy(inst,init->instance, INST_SZ);
  305.     }
  306. #ifdef COMMENT
  307.     if ( vflag )
  308.         printf("Kerberos IV initializationrn");
  309. #endif /* COMMENT */
  310.     if (!username || !username[0]) {
  311.         debug(F100,"ck_krb4_initTGT no username specified","",0);
  312.         printf("?Invalid principal specified.rn");
  313.         krb4_errno = 0;
  314.         makestr(&krb4_errmsg,"No principal specified");
  315.         return(-1);
  316.     }
  317.     if (!*realm) {
  318.         ckstrncpy(realm,ck_krb4_getrealm(),REALM_SZ);
  319.     }
  320.     if (pflag) {
  321.         k_errno = krb_get_pw_in_tkt_preauth( aname, inst, realm,
  322.                                              "krbtgt", realm,
  323.                                              lifetime,
  324.                                              password[0]? password:
  325.                                              NULL);
  326. if (k_errno == -1) {    /* preauth method not available */
  327.     k_errno = krb_get_pw_in_tkt(aname,
  328.  inst, realm,
  329.  "krbtgt", realm,
  330.  lifetime,
  331.  password[0]? password:
  332.  NULL);
  333. }
  334.     } else {
  335.         k_errno = krb_get_pw_in_tkt(aname,
  336.                                      inst, realm,
  337.                                      "krbtgt", realm,
  338.                                      lifetime,
  339.                                      password[0]? password:
  340.                                      NULL);
  341.     }
  342.     if (k_errno) {
  343.         printf("%s for principal %s%s%s@%srn",
  344. krb_get_err_text_entry(k_errno), aname,
  345.                 inst[0]?".":"", inst, realm);
  346.         krb4_errno = k_errno;
  347.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  348. return(-1);
  349.     } else if (vflag) {
  350. printf("Result from realm %s: ", realm);
  351. printf("%srn", krb_get_err_text_entry(k_errno));
  352.     }
  353.     krb4_errno = k_errno;
  354.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  355.     return(0);
  356. }
  357. #endif /* KINIT */
  358. #ifdef KDESTROY
  359. int
  360. #ifdef CK_ANSIC
  361. ck_krb4_destroy(struct krb_op_data * op)
  362. #else
  363. ck_krb4_destroy(op) struct krb_op_data * op;
  364. #endif
  365. {
  366.     int k_errno=0;
  367.     if ( !ck_krb4_is_installed() )
  368.         return(-1);
  369.     k_errno = dest_tkt();
  370.     krb4_errno = k_errno;
  371.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  372.     if (k_errno == 0)
  373.         printf("Tickets destroyed.rn");
  374.     else if (k_errno == RET_TKFIL)
  375.         printf("No tickets to destroy.rn");
  376.     else {
  377.         printf("Tickets MAY NOT be destroyed.rn");
  378.         return(-1);
  379.     }
  380.     return(0);
  381. }
  382. #endif /* KDESTROY */
  383. #ifdef KLIST
  384. _PROTOTYP(static int display_tktfile,(char *, int, int, int));
  385. int
  386. #ifdef CK_ANSIC
  387. ck_krb4_list_creds(struct krb_op_data * op)
  388. #else
  389. ck_krb4_list_creds(op) struct krb_op_data * op;
  390. #endif
  391. {
  392.     int     long_form = 1;
  393.     int     tgt_test = 0;
  394.     int     do_srvtab = 0;
  395.     int     show_kvnos = 0;
  396.     char   *tkt_file = NULL;
  397.     if ( !ck_krb4_is_installed() )
  398.         return(-1);
  399.     if ( op->cache )
  400.         tkt_file = op->cache;
  401.     if ( k4debug ) {
  402.         show_kvnos = 1;
  403.     }
  404.     if (do_srvtab)
  405. return(display_srvtab(tkt_file));
  406.     else
  407. return(display_tktfile(tkt_file, tgt_test, long_form, show_kvnos));
  408. }
  409. #ifndef KRB5
  410. static int timestamp_width=0;
  411. static char   *
  412. #ifdef CK_ANSIC
  413. short_date(long   *dp)
  414. #else
  415. short_date(dp) long   *dp;
  416. #endif
  417. {
  418.     register char *cp;
  419.     extern char *ctime();
  420.     cp = ctime(dp) + 4;
  421.     cp[15] = '';
  422.     return (cp);
  423. }
  424. static VOID
  425. #ifdef CK_ANSIC
  426. printtime(time_t tv)
  427. #else
  428. printtime(tv) time_t tv;
  429. #endif
  430. {
  431.     char timestring[BUFSIZ];
  432.     char format[12];
  433.     char fill;
  434.     fill = ' ';
  435.     sprintf(format,"%%-%ds",timestamp_width);
  436.     printf(format,short_date(&tv));
  437. }
  438. #endif /* KRB5 */
  439. static int
  440. #ifdef CK_ANSIC
  441. display_tktfile(char *file, int tgt_test, int long_form, int show_kvnos)
  442. #else
  443. display_tktfile(file,tgt_test,long_form,show_kvnos)
  444.     char *file; int tgt_test; int long_form; int show_kvnos;
  445. #endif
  446. {
  447.     char    pname[ANAME_SZ];
  448.     char    pinst[INST_SZ];
  449.     char    prealm[REALM_SZ];
  450.     char    buf1[20], buf2[20];
  451.     int     k_errno;
  452. #ifdef OS2
  453.     LEASH_CREDENTIALS creds;
  454. #else /* OS2 */
  455.     CREDENTIALS creds;
  456. #endif /* OS2 */
  457.     int     header = 1;
  458.     file = tkt_string();
  459.     if (long_form) {
  460. printf("Ticket cache:      %srn", file);
  461.     }
  462.     /*
  463.      * Since krb_get_tf_realm will return a ticket_file error,
  464.      * we will call tf_init and tf_close first to filter out
  465.      * things like no ticket file.  Otherwise, the error that
  466.      * the user would see would be
  467.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  468.      * instead of
  469.      * klist: No ticket file (tf_util)
  470.      */
  471.     /* Open ticket file */
  472.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  473. if (!tgt_test)
  474.             printf("%srn", krb_get_err_text_entry (k_errno));
  475.         krb4_errno = k_errno;
  476.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  477.         return(-1);
  478.     }
  479.     /* Close ticket file */
  480.     (void) tf_close();
  481.     /*
  482.      * We must find the realm of the ticket file here before calling
  483.      * tf_init because since the realm of the ticket file is not
  484.      * really stored in the principal section of the file, the
  485.      * routine we use must itself call tf_init and tf_close.
  486.      */
  487.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  488. if (!tgt_test)
  489.     printf("can't find realm of ticket file: %srn",
  490.     krb_get_err_text_entry (k_errno));
  491.         krb4_errno = k_errno;
  492.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  493. return(-1);
  494.     }
  495.     /* Open ticket file */
  496.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  497. if (!tgt_test)
  498.             printf("%srn", krb_get_err_text_entry (k_errno));
  499.         krb4_errno = k_errno;
  500.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  501. return(-1);
  502.     }
  503.     /* Get principal name and instance */
  504.     if ((k_errno = tf_get_pname(pname)) ||
  505.          (k_errno = tf_get_pinst(pinst))) {
  506.         (void) tf_close();
  507.         if (!tgt_test)
  508.             printf("%srn", krb_get_err_text_entry (k_errno));
  509.         krb4_errno = k_errno;
  510.         makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  511.         return(-1);
  512.     }
  513.     /*
  514.      * You may think that this is the obvious place to get the
  515.      * realm of the ticket file, but it can't be done here as the
  516.      * routine to do this must open the ticket file.  This is why
  517.      * it was done before tf_init.
  518.      */
  519.     if (!tgt_test && long_form)
  520. printf("Default principal: %s%s%s%s%srnrn", pname,
  521.        (pinst[0] ? "." : ""), pinst,
  522.        (prealm[0] ? "@" : ""), prealm);
  523.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  524. if (!tgt_test && long_form && header) {
  525.     printf("%-15s  %-15s  %srn",
  526.    "Valid starting", "Expires", "Service principal");
  527.     header = 0;
  528. }
  529. if (tgt_test) {
  530.     creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  531.     if (!strcmp(creds.service, "krbtgt") &&
  532. !strcmp(creds.instance, prealm)) {
  533.                 krb4_errno = k_errno;
  534.                 makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  535.                 (void) tf_close();
  536. if (time(0) < creds.issue_date) {
  537.     return(0); /* tgt hasn't expired */
  538. } else {
  539.     return(-1); /* has expired */
  540.                 }
  541.     }
  542.     continue; /* not a tgt */
  543. }
  544. if (long_form) {
  545.             timestamp_width = 17;       /* for k5 display function */
  546.                                         /* if available            */
  547.             printtime(creds.issue_date);
  548.     creds.issue_date += ((unsigned char) creds.lifetime) * 5 * 60;
  549.             if ( time(0) < creds.issue_date )
  550.                 printtime(creds.issue_date);
  551.             else
  552.                 printf("*** expired ***  ");
  553. }
  554.         if (show_kvnos)
  555.   printf("%s%s%s%s%s (%d)rn",
  556.  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  557.  (creds.realm[0] ? "@" : ""), creds.realm, creds.kvno);
  558. else
  559.   printf("%s%s%s%s%srn",
  560.  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  561.  (creds.realm[0] ? "@" : ""), creds.realm);
  562. #ifdef OS2
  563. if ( creds.address[0] )
  564.     printf("   Address: %srn",creds.address);
  565. #endif /* OS2 */
  566.     }
  567.     (void) tf_close();
  568.     if (tgt_test) {
  569. return(-1);
  570.     }/* no tgt found */
  571.     if (header && long_form && k_errno == EOF) {
  572. printf("No tickets in file.rn");
  573.     }
  574.     krb4_errno = k_errno;
  575.     makestr(&krb4_errmsg,krb_get_err_text_entry(k_errno));
  576.     return(0);
  577. }
  578. #ifdef COMMENT
  579. /* Just so we remember what the command line interface looked like */
  580. usage()
  581. {
  582.     printf(
  583. "Usage: [ -s | -t ] [ -file filename ] [ -srvtab ] [ -version ]rn");
  584.     return(-1);
  585. }
  586. #endif /* COMMENT */
  587. /* adapted from getst() in librkb */
  588. /*
  589.  * ok_getst() takes a file descriptor, a string and a count.  It reads
  590.  * from the file until either it has read "count" characters, or until
  591.  * it reads a null byte.  When finished, what has been read exists in
  592.  * the given string "s".  If "count" characters were actually read, the
  593.  * last is changed to a null, so the returned string is always null-
  594.  * terminated.  ok_getst() returns the number of characters read, including
  595.  * the null terminator.
  596.  *
  597.  * If there is a read error, it returns -1 (like the read(2) system call)
  598.  */
  599. static int
  600. #ifdef CK_ANSIC
  601. ok_getst(int fd, register char *s, int n)
  602. #else
  603. ok_getst(fd, s, n) int fd; register char *s; int n;
  604. #endif
  605. {
  606.     register int count = n;
  607.     int err;
  608.     while ((err = read(fd, s, 1)) > 0 && --count)
  609.         if (*s++ == '')
  610.             return (n - count);
  611.     if (err < 0)
  612. return(-1);
  613.     *s = '';
  614.     return (n - count);
  615. }
  616. int
  617. #ifdef CK_ANSIC
  618. display_srvtab(char *file)
  619. #else
  620. display_srvtab(file) char *file;
  621. #endif
  622. {
  623.     int stab;
  624.     char serv[SNAME_SZ];
  625.     char inst[INST_SZ];
  626.     char rlm[REALM_SZ];
  627.     unsigned char key[8];
  628.     unsigned char vno;
  629.     int count;
  630.     printf("Server key file:   %srn", file);
  631.     if ((stab = open(file, O_RDONLY, 0400)) < 0) {
  632. perror(file);
  633. return(-1);
  634.     }
  635.     printf("%-15s %-15s %-10s %srn","Service","Instance","Realm",
  636.    "Key Version");
  637.     printf("------------------------------------------------------rn");
  638.     /* argh. getst doesn't return error codes, it silently fails */
  639.     while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0)
  640.    && ((count = ok_getst(stab, inst, INST_SZ)) > 0)
  641.    && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) {
  642. if (((count = read(stab,(char *) &vno,1)) != 1) ||
  643.      ((count = read(stab,(char *) key,8)) != 8)) {
  644.     if (count < 0)
  645. perror("reading from key file");
  646.     else
  647. printf("key file truncatedrn");
  648.     return(-1);
  649. }
  650. printf("%-15s %-15s %-15s %drn",serv,inst,rlm,vno);
  651.     }
  652.     if (count < 0)
  653. perror(file);
  654.     (void) close(stab);
  655.     return(0);
  656. }
  657. #endif /* KLIST */
  658. #else /* KRB4 */
  659. int
  660. ck_krb4_autoget_TGT(char * dummy)
  661. {
  662.     return(-1);
  663. }
  664. #ifdef CK_KERBEROS
  665. int
  666. #ifdef CK_ANSIC
  667. ck_krb4_initTGT(struct krb_op_data * op, struct krb4_init_data * init)
  668. #else
  669. ck_krb4_initTGT(op,init)
  670.     struct krb_op_data * op, struct krb4_init_data * init
  671. #endif
  672. {
  673.     return(-1);
  674. }
  675. #ifdef CK_ANSIC
  676. ck_krb4_destroy(struct krb_op_data * op)
  677. #else
  678. ck_krb4_destroy(op) struct krb_op_data * op;
  679. #endif
  680. {
  681.     return(-1);
  682. }
  683. int
  684. #ifdef CK_ANSIC
  685. ck_krb4_list_creds(struct krb_op_data * op)
  686. #else
  687. ck_krb4_list_creds(op) struct krb_op_data * op;
  688. #endif
  689. {
  690.     return(-1);
  691. }
  692. #else /* CK_KERBEROS */
  693. int ck_krb4_initTGT(void * a, void *b)
  694. {
  695.     return(-1);
  696. }
  697. int ck_krb4_destroy(void *a)
  698. {
  699.     return(-1);
  700. }
  701. int ck_krb4_list_creds(void *a)
  702. {
  703.     return(-1);
  704. }
  705. #endif /* CK_KERBEROS */
  706. #endif /* KRB4 */
  707. /* The following functions are used to implement the Kermit Script Language */
  708. /* functions                                                                */
  709. struct tkt_list_item {
  710.     char * name;
  711.     struct tkt_list_item * next;
  712. };
  713. static struct tkt_list_item * k4_tkt_list = NULL;
  714. int
  715. #ifdef CK_ANSIC
  716. ck_krb4_get_tkts(VOID)
  717. #else
  718. ck_krb4_get_tkts()
  719. #endif
  720. {
  721. #ifdef KRB4
  722.     char   *file=NULL;
  723.     char    pname[ANAME_SZ];
  724.     char    pinst[INST_SZ];
  725.     char    prealm[REALM_SZ];
  726.     char    buf1[20], buf2[20];
  727.     int     k_errno;
  728. #ifdef OS2
  729.     LEASH_CREDENTIALS creds;
  730. #else /* OS2 */
  731.     CREDENTIALS creds;
  732. #endif /* OS2 */
  733.     int     tkt_count=0;
  734.     struct  tkt_list_item ** list = &k4_tkt_list;
  735.     while ( k4_tkt_list ) {
  736.         struct tkt_list_item * next;
  737.         next = k4_tkt_list->next;
  738.         free(k4_tkt_list->name);
  739.         free(k4_tkt_list);
  740.         k4_tkt_list = next;
  741.     }
  742.     if ( !ck_krb4_is_installed() )
  743.         return(-1);
  744.     file = tkt_string();
  745.     /*
  746.      * Since krb_get_tf_realm will return a ticket_file error,
  747.      * we will call tf_init and tf_close first to filter out
  748.      * things like no ticket file.  Otherwise, the error that
  749.      * the user would see would be
  750.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  751.      * instead of
  752.      * klist: No ticket file (tf_util)
  753.      */
  754.     /* Open ticket file */
  755.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  756.         return(-1);
  757.     }
  758.     /* Close ticket file */
  759.     (void) tf_close();
  760.     /*
  761.      * We must find the realm of the ticket file here before calling
  762.      * tf_init because since the realm of the ticket file is not
  763.      * really stored in the principal section of the file, the
  764.      * routine we use must itself call tf_init and tf_close.
  765.      */
  766.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  767. return(-1);
  768.     }
  769.     /* Open ticket file */
  770.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  771. return(-1);
  772.     }
  773.     /* Get principal name and instance */
  774.     if ((k_errno = tf_get_pname(pname)) ||
  775.          (k_errno = tf_get_pinst(pinst))) {
  776.         return(-1);
  777.     }
  778.     /*
  779.      * You may think that this is the obvious place to get the
  780.      * realm of the ticket file, but it can't be done here as the
  781.      * routine to do this must open the ticket file.  This is why
  782.      * it was done before tf_init.
  783.      */
  784.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  785.         char tkt_buf[256];
  786.         sprintf(tkt_buf,"%s%s%s%s%s",
  787.  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  788.  (creds.realm[0] ? "@" : ""), creds.realm);
  789.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  790.         (*list)->name = strdup(tkt_buf);
  791.         (*list)->next = NULL;
  792.         list = &((*list)->next);
  793.         tkt_count++;
  794.     }
  795.     tf_close();
  796.     return(tkt_count);
  797. #else /* KRB4 */
  798.     return(0);
  799. #endif /* KRB4 */
  800. }
  801. char *
  802. #ifdef CK_ANSIC
  803. ck_krb4_get_next_tkt(VOID)
  804. #else
  805. ck_krb4_get_next_tkt()
  806. #endif
  807. {
  808. #ifdef KRB4
  809.     static char * s=NULL;
  810.     struct tkt_list_item * next=NULL;
  811.     if ( s ) {
  812.         free(s);
  813.         s = NULL;
  814.     }
  815.     if ( k4_tkt_list == NULL )
  816.         return(NULL);
  817.     next = k4_tkt_list->next;
  818.     s = k4_tkt_list->name;
  819.     free(k4_tkt_list);
  820.     k4_tkt_list = next;
  821.     return(s);
  822. #else /* KRB4 */
  823.     return(NULL);
  824. #endif /* KRB4 */
  825. }
  826. int
  827. #ifdef CK_ANSIC
  828. ck_krb4_tkt_isvalid(char * tktname)
  829. #else
  830. ck_krb4_tkt_isvalid(tktname) char * tktname;
  831. #endif
  832. {
  833. #ifdef KRB4
  834.     char   *file=NULL;
  835.     char    pname[ANAME_SZ];
  836.     char    pinst[INST_SZ];
  837.     char    prealm[REALM_SZ];
  838.     char    buf1[20], buf2[20];
  839.     int     k_errno;
  840.     time_t  issue_t, expire_t, now_t;
  841. #ifdef OS2
  842.     LEASH_CREDENTIALS creds;
  843. #else /* OS2 */
  844.     CREDENTIALS creds;
  845. #endif /* OS2 */
  846.     if ( !ck_krb4_is_installed() )
  847.         return(-1);
  848.     debug(F110,"ck_krb4_tkt_isvalid","tkt_string",0);
  849.     file = tkt_string();
  850.     /*
  851.      * Since krb_get_tf_realm will return a ticket_file error,
  852.      * we will call tf_init and tf_close first to filter out
  853.      * things like no ticket file.  Otherwise, the error that
  854.      * the user would see would be
  855.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  856.      * instead of
  857.      * klist: No ticket file (tf_util)
  858.      */
  859.     /* Open ticket file */
  860.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  861.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  862.         return(-1);
  863.     }
  864.     /* Close ticket file */
  865.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  866.     (void) tf_close();
  867.     /*
  868.      * We must find the realm of the ticket file here before calling
  869.      * tf_init because since the realm of the ticket file is not
  870.      * really stored in the principal section of the file, the
  871.      * routine we use must itself call tf_init and tf_close.
  872.      */
  873.     debug(F110,"ck_krb4_tkt_isvalid","krb_get_tf_realm",0);
  874.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  875. return(-1);
  876.     }
  877.     /* Open ticket file */
  878.     debug(F110,"ck_krb4_tkt_isvalid","tf_init",0);
  879.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  880. return(-1);
  881.     }
  882.     /* Get principal name and instance */
  883.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_name/tf_get_pinst",0);
  884.     if ((k_errno = tf_get_pname(pname)) ||
  885.          (k_errno = tf_get_pinst(pinst))) {
  886.         /* Close ticket file */
  887.         debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  888.         (void) tf_close();
  889.         return(-1);
  890.     }
  891.     /*
  892.      * You may think that this is the obvious place to get the
  893.      * realm of the ticket file, but it can't be done here as the
  894.      * routine to do this must open the ticket file.  This is why
  895.      * it was done before tf_init.
  896.      */
  897.     debug(F110,"ck_krb4_tkt_isvalid","tf_get_cred",0);
  898.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  899.         char tkt_buf[256];
  900.         sprintf(tkt_buf,"%s%s%s%s%s",
  901.  creds.service, (creds.instance[0] ? "." : ""), creds.instance,
  902.  (creds.realm[0] ? "@" : ""), creds.realm);
  903.         if ( !strcmp(tktname,tkt_buf) ) {
  904.             /* we found the ticket we are looking for */
  905.             issue_t = creds.issue_date;
  906.             expire_t = creds.issue_date
  907.                 + ((unsigned char) creds.lifetime) * 5 * 60;
  908.             now_t = time(0);
  909.             /* We add a 5 minutes fudge factor to compensate for potential */
  910.             /* clock skew errors between the KDC and K95's host OS         */
  911.             if ( now_t >= (issue_t-300) &&
  912.                  now_t < expire_t)
  913.             {
  914. #ifdef OS2
  915. #ifdef CHECKADDRS
  916. if ( krb4_checkaddrs ) {
  917.     extern char myipaddr[20];       /* From ckcnet.c */
  918.     if ( !myipaddr[0] ) {
  919. int i;
  920. char buf[60];
  921. for ( i=0;i<64;i++ ) {
  922.     if ( getlocalipaddrs(buf,60,i) < 0 )
  923. break;
  924.     if ( !strcmp(buf,creds.address) ) {
  925. /* Close ticket file */
  926. debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  927. (void) tf_close();
  928. return(1); /* They're the same */
  929.     }
  930. }
  931. /* Close ticket file */
  932. debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  933. (void) tf_close();
  934. return(0);                  /* They're different */
  935.     } else if ( strcmp(myipaddr,creds.address) ) {
  936. /* Close ticket file */
  937. debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  938. (void) tf_close();
  939. return(0);                  /* They're different */
  940.     }
  941.     else {
  942. /* Close ticket file */
  943. debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  944. (void) tf_close();
  945. return(1);                  /* They're the same */
  946.     }
  947. } else {
  948.     /* Close ticket file */
  949.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  950.     (void) tf_close();
  951.     return(1);                  /* They're the same */
  952. }
  953. #else /* CHECKADDRS */
  954.                 /* Close ticket file */
  955.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  956.                 (void) tf_close();
  957.                 return(1);      /* valid but no ip address check */
  958. #endif /* CHECKADDRS */
  959. #else /* OS2 */
  960.                 /* Close ticket file */
  961.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  962.                 (void) tf_close();
  963.                 return(1);      /* Valid but no ip address check */
  964. #endif /* OS2 */
  965.             }
  966.             else {
  967.                 /* Close ticket file */
  968.                 debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  969.                 (void) tf_close();
  970.                 return(0);      /* expired or otherwise invalid */
  971.             }
  972.         }
  973.     }
  974.     /* Close ticket file */
  975.     debug(F110,"ck_krb4_tkt_isvalid","tf_close",0);
  976.     (void) tf_close();
  977.     return(0);                  /* could not find the desired ticket */
  978. #else /* KRB4 */
  979.     return(-1);
  980. #endif /* KRB4 */
  981. }
  982. int
  983. #ifdef CK_ANSIC
  984. ck_krb4_is_tgt_valid(VOID)
  985. #else
  986. ck_krb4_is_tgt_valid()
  987. #endif
  988. {
  989. #ifdef KRB4
  990.     char tgt[256];
  991.     char * s;
  992.     int rc = 0;
  993.     s = krb4_d_realm ? krb4_d_realm : ck_krb4_getrealm();
  994.     sprintf(tgt,"krbtgt.%s@%s",s,s);
  995.     rc = ck_krb4_tkt_isvalid(tgt);
  996.     debug(F111,"ck_krb4_is_tgt_valid",tgt,rc);
  997.     return(rc > 0);
  998. #else /* KRB4 */
  999.     return(0);
  1000. #endif /* KRB4 */
  1001. }
  1002. int
  1003. #ifdef CK_ANSIC
  1004. ck_krb4_tkt_time(char * tktname)
  1005. #else
  1006. ck_krb4_tkt_time(tktname) char * tktname;
  1007. #endif
  1008. {
  1009. #ifdef KRB4
  1010.     char   *file=NULL;
  1011.     char    pname[ANAME_SZ];
  1012.     char    pinst[INST_SZ];
  1013.     char    prealm[REALM_SZ];
  1014.     char    buf1[20], buf2[20];
  1015.     int     k_errno;
  1016. #ifdef OS2
  1017.     LEASH_CREDENTIALS creds;
  1018. #else /* OS2 */
  1019.     CREDENTIALS creds;
  1020. #endif /* OS2 */
  1021.     if ( !ck_krb4_is_installed() )
  1022.         return(-1);
  1023.     file = tkt_string();
  1024.     /*
  1025.      * Since krb_get_tf_realm will return a ticket_file error,
  1026.      * we will call tf_init and tf_close first to filter out
  1027.      * things like no ticket file.  Otherwise, the error that
  1028.      * the user would see would be
  1029.      * klist: can't find realm of ticket file: No ticket file (tf_util)
  1030.      * instead of
  1031.      * klist: No ticket file (tf_util)
  1032.      */
  1033.     /* Open ticket file */
  1034.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  1035.         return(-1);
  1036.     }
  1037.     /* Close ticket file */
  1038.     (void) tf_close();
  1039.     /*
  1040.      * We must find the realm of the ticket file here before calling
  1041.      * tf_init because since the realm of the ticket file is not
  1042.      * really stored in the principal section of the file, the
  1043.      * routine we use must itself call tf_init and tf_close.
  1044.      */
  1045.     if ((k_errno = krb_get_tf_realm(file, prealm)) != AUTH_SUCCESS) {
  1046. return(-1);
  1047.     }
  1048.     /* Open ticket file */
  1049.     if (k_errno = tf_init(file, R_TKT_FIL)) {
  1050. return(-1);
  1051.     }
  1052.     /* Get principal name and instance */
  1053.     if ((k_errno = tf_get_pname(pname)) ||
  1054.          (k_errno = tf_get_pinst(pinst))) {
  1055.         tf_close();
  1056.         return(-1);
  1057.     }
  1058.     /*
  1059.      * You may think that this is the obvious place to get the
  1060.      * realm of the ticket file, but it can't be done here as the
  1061.      * routine to do this must open the ticket file.  This is why
  1062.      * it was done before tf_init.
  1063.      */
  1064.     while ((k_errno = tf_get_cred((CREDENTIALS *)&creds)) == AUTH_SUCCESS) {
  1065.         char tkt_buf[256];
  1066.         sprintf(tkt_buf,"%s%s%s%s%s",
  1067.  creds.service, (creds.instance[0] ? "." : ""),
  1068.                  creds.instance,
  1069.  (creds.realm[0] ? "@" : ""), creds.realm);
  1070.         if ( !strcmp(tktname,tkt_buf) ) {
  1071.             /* we found the ticket we are looking for */
  1072.             int n = (creds.issue_date
  1073.                       + (((unsigned char) creds.lifetime) * 5 * 60))
  1074.                 - time(0);
  1075.             tf_close();
  1076.             return(n <= 0 ? 0 : n);
  1077.         }
  1078.     }
  1079.     tf_close();
  1080.     return(0);                  /* could not find the desired ticket */
  1081. #else /* KRB4 */
  1082.     return(-1);
  1083. #endif /* KRB4 */
  1084. }
  1085. char *
  1086. #ifdef CK_ANSIC
  1087. ck_krb4_getrealm(void)
  1088. #else
  1089. ck_krb4_getrealm()
  1090. #endif
  1091. {
  1092. #ifdef KRB4
  1093.     char   *file=NULL;
  1094.     int     k_errno;
  1095.     static char realm[256]="";
  1096.     realm[0]='';
  1097.     if ( !ck_krb4_is_installed() )
  1098.         return(realm);
  1099.     /* Try to get realm from ticket file */
  1100.     /* If failure get the local realm    */
  1101.     /*
  1102.     * Since krb_get_tf_realm will return a ticket_file error,
  1103.     * we will call tf_init and tf_close first to filter out
  1104.     * things like no ticket file.
  1105.     */
  1106.     /* Open ticket file */
  1107.     file = tkt_string();
  1108.     if (file == NULL || !file[0])
  1109.         return(realm);
  1110.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  1111.         /* Close ticket file */
  1112.         (void) tf_close();
  1113.         k_errno = krb_get_tf_realm(file, realm);
  1114.     }
  1115.     if (k_errno != KSUCCESS) {
  1116.         k_errno = krb_get_lrealm(realm, 1);
  1117.     }
  1118.     return(realm);
  1119. #else /* KRB4 */
  1120.     return("");
  1121. #endif /* KRB4 */
  1122. }
  1123. char *
  1124. #ifdef CK_ANSIC
  1125. ck_krb4_getprincipal(void)
  1126. #else
  1127. ck_krb4_getprincipal()
  1128. #endif
  1129. {
  1130. #ifdef KRB4
  1131.     char   *file=NULL;
  1132.     int     k_errno;
  1133.     static char principal[256]="";
  1134.     char        instance[256]="";
  1135.     char        realm[256]="";
  1136.     principal[0]='';
  1137.     if ( !ck_krb4_is_installed() )
  1138.         return(principal);
  1139.     /* Try to get realm from ticket file */
  1140.     /* If failure get the local realm    */
  1141.     /*
  1142.     * Since krb_get_tf_realm will return a ticket_file error,
  1143.     * we will call tf_init and tf_close first to filter out
  1144.     * things like no ticket file.
  1145.     */
  1146.     /* Open ticket file */
  1147.     file = tkt_string();
  1148.     if (file == NULL || !file[0])
  1149.         return(principal);
  1150.     if ((k_errno = tf_init(file, R_TKT_FIL)) == KSUCCESS) {
  1151.         /* Close ticket file */
  1152.         (void) tf_close();
  1153.         k_errno = krb_get_tf_fullname(file, principal, instance, realm);
  1154.     }
  1155.     return(principal);
  1156. #else /* KRB4 */
  1157.     return("");
  1158. #endif /* KRB4 */
  1159. }
  1160. static struct tkt_list_item * k5_tkt_list = NULL;
  1161. int
  1162. #ifdef CK_ANSIC
  1163. ck_krb5_get_tkts(char * cc_name)
  1164. #else
  1165. ck_krb5_get_tkts(cc_name) char * cc_name;
  1166. #endif
  1167. {
  1168. #ifdef KRB5
  1169.     krb5_context kcontext;
  1170.     krb5_error_code retval;
  1171.     krb5_ccache cache = NULL;
  1172.     krb5_cc_cursor cur;
  1173.     krb5_creds creds;
  1174.     krb5_principal princ=NULL;
  1175.     krb5_flags flags=0;
  1176.     krb5_error_code code=0;
  1177.     int exit_status = 0;
  1178.     int     tkt_count=0;
  1179.     struct  tkt_list_item ** list = &k5_tkt_list;
  1180.     while ( k5_tkt_list ) {
  1181.         struct tkt_list_item * next;
  1182.         next = k5_tkt_list->next;
  1183.         free(k5_tkt_list->name);
  1184.         free(k5_tkt_list);
  1185.         k5_tkt_list = next;
  1186.     }
  1187.     if ( !ck_krb5_is_installed() )
  1188.         return(-1);
  1189.     retval = krb5_init_context(&kcontext);
  1190.     if (retval) {
  1191.         debug(F101,"ck_krb5_get_tkts while initializing krb5","",retval);
  1192.         return(-1);
  1193.     }
  1194.     code = k5_get_ccache(kcontext,&cache,cc_name);
  1195.     if (code != 0) {
  1196.         debug(F111,"ck_krb5_get_tkts while getting ccache",
  1197.                error_message(code),code);
  1198.         tkt_count = -1;
  1199.         goto exit_k5_get_tkt;
  1200.     }
  1201.     flags = 0; /* turns off OPENCLOSE mode */
  1202.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1203. if (code == ENOENT) {
  1204.             debug(F111,"ck_krb5_get_tkts (ticket cache)",
  1205.                    krb5_cc_get_name(kcontext, cache),code);
  1206. } else {
  1207.             debug(F111,
  1208.  "ck_krb5_get_tkts while setting cache flags (ticket cache)",
  1209.                   krb5_cc_get_name(kcontext, cache),code);
  1210. }
  1211.         tkt_count = -1;
  1212.         goto exit_k5_get_tkt;
  1213.     }
  1214.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  1215.         debug(F101,"ck_krb5_get_tkts while retrieving principal name",
  1216.                "",code);
  1217.         tkt_count = -1;
  1218.         goto exit_k5_get_tkt;
  1219.     }
  1220.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  1221.         debug(F101,"ck_krb5_get_tkts while unparsing principal name",
  1222.                "",code);
  1223.         tkt_count = -1;
  1224.         goto exit_k5_get_tkt;
  1225.     }
  1226.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  1227.         debug(F101,"ck_krb5_get_tkts while starting to retrieve tickets",
  1228.                "",code);
  1229.         tkt_count = -1;
  1230.         goto exit_k5_get_tkt;
  1231.     }
  1232.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  1233.         char *sname=NULL;
  1234.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  1235.         if (retval) {
  1236.             debug(F101,
  1237.   "ck_krb5_get_tkts while unparsing server name","",retval);
  1238.             tkt_count = -1;
  1239.             goto exit_k5_get_tkt;
  1240.         }
  1241.         *list = (struct tkt_list_item *) malloc(sizeof(struct tkt_list_item));
  1242.         (*list)->name = sname;
  1243.         (*list)->next = NULL;
  1244.         list = &((*list)->next);
  1245. krb5_free_cred_contents(kcontext, &creds);
  1246.         tkt_count++;
  1247.     }
  1248.     if (code == KRB5_CC_END) {
  1249. if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  1250.             debug(F101,"ck_krb5_get_tkts while finishing ticket retrieval",
  1251.                    "",code);
  1252.             tkt_count = -1;
  1253.             goto exit_k5_get_tkt;
  1254. }
  1255. flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
  1256. if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1257.             debug(F101,"ck_krb5_get_tkts while closing ccache",
  1258.                    "",code);
  1259.             tkt_count = -1;
  1260.             goto exit_k5_get_tkt;
  1261. }
  1262.     } else {
  1263.         debug(F101,"ck_krb5_get_tkts while retrieving a ticket","",code);
  1264.         tkt_count = -1;
  1265.         goto exit_k5_get_tkt;
  1266.     }
  1267.   exit_k5_get_tkt:
  1268.     krb5_free_principal(kcontext,princ);
  1269.     krb5_free_unparsed_name(kcontext,defname);
  1270.     krb5_cc_close(kcontext,cache);
  1271.     krb5_free_context(kcontext);
  1272.     return(tkt_count);
  1273. #else /* KRB5 */
  1274.     return(0);
  1275. #endif /* KRB5 */
  1276. }
  1277. char *
  1278. #ifdef CK_ANSIC
  1279. ck_krb5_get_next_tkt(VOID)
  1280. #else
  1281. ck_krb5_get_next_tkt()
  1282. #endif
  1283. {
  1284. #ifdef KRB5
  1285.     static char * s=NULL;
  1286.     struct tkt_list_item * next=NULL;
  1287.     if ( s ) {
  1288.         free(s);
  1289.         s = NULL;
  1290.     }
  1291.     if ( k5_tkt_list == NULL )
  1292.         return(NULL);
  1293.     next = k5_tkt_list->next;
  1294.     s = k5_tkt_list->name;
  1295.     free(k5_tkt_list);
  1296.     k5_tkt_list = next;
  1297.     return(s);
  1298. #else /* KRB5 */
  1299.     return(NULL);
  1300. #endif /* KRB5 */
  1301. }
  1302. char *
  1303. #ifdef CK_ANSIC
  1304. ck_krb5_tkt_flags(char * cc_name, char * tktname)
  1305. #else
  1306. ck_krb5_tkt_flags(cc_name,tktname) char * cc_name; char * tktname;
  1307. #endif
  1308. {
  1309. #ifdef KRB5
  1310.     krb5_context kcontext;
  1311.     krb5_error_code retval;
  1312.     krb5_ccache cache = NULL;
  1313.     krb5_cc_cursor cur;
  1314.     krb5_creds creds;
  1315.     krb5_principal princ=NULL;
  1316.     krb5_flags flags=0;
  1317.     krb5_error_code code=0;
  1318.     char * flag_str = "";
  1319.     if ( !ck_krb5_is_installed() )
  1320.         return("");
  1321.     retval = krb5_init_context(&kcontext);
  1322.     if (retval) {
  1323.         debug(F101,"ck_krb5_tkt_flags while initializing krb5","",retval);
  1324.         return("");
  1325.     }
  1326.     code = k5_get_ccache(kcontext,&cache,cc_name);
  1327.     if (code != 0) {
  1328.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  1329.                error_message(code),code);
  1330.         goto exit_k5_get_tkt;
  1331.     }
  1332.     flags = 0; /* turns off OPENCLOSE mode */
  1333.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1334. if (code == ENOENT) {
  1335.             debug(F111,"ck_krb5_tkt_flags (ticket cache)",
  1336.                    krb5_cc_get_name(kcontext, cache),code);
  1337. } else {
  1338.             debug(F111,
  1339.  "ck_krb5_tkt_flags while setting cache flags (ticket cache)",
  1340.                   krb5_cc_get_name(kcontext, cache),code);
  1341. }
  1342.         retval = -1;
  1343.         goto exit_k5_get_tkt;
  1344.     }
  1345.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  1346.         debug(F101,"ck_krb5_tkt_flags while retrieving principal name",
  1347.                "",code);
  1348.         retval = -1;
  1349.         goto exit_k5_get_tkt;
  1350.     }
  1351.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  1352.         debug(F101,"ck_krb5_tkt_flags while unparsing principal name",
  1353.                "",code);
  1354.         retval = -1;
  1355.         goto exit_k5_get_tkt;
  1356.     }
  1357.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  1358.         debug(F101,"ck_krb5_tkt_flags while starting to retrieve tickets",
  1359.                "",code);
  1360.         retval = -1;
  1361.         goto exit_k5_get_tkt;
  1362.     }
  1363.     if ((code = krb5_timeofday(kcontext, &now))) {
  1364.         if (!status_only)
  1365.             debug(F101,"ck_krb5_tkt_flags while getting time of day.",
  1366.                    "",code);
  1367.         retval = -1;
  1368.         goto exit_k5_get_tkt;
  1369.     }
  1370.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  1371.         char *sname=NULL;
  1372.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  1373.         if (retval) {
  1374.             debug(F101,
  1375.   "ck_krb5_tkt_flags while unparsing server name","",retval);
  1376.             retval = -1;
  1377.             krb5_free_cred_contents(kcontext, &creds);
  1378.             goto exit_k5_get_tkt;
  1379.         }
  1380.         if ( !strcmp(sname,tktname) ) {
  1381.             /* we found the ticket we are looking for */
  1382.             flag_str = flags_string(&creds);
  1383.             krb5_free_cred_contents(kcontext, &creds);
  1384.             code = KRB5_CC_END;
  1385.             break;
  1386.         }
  1387. krb5_free_cred_contents(kcontext, &creds);
  1388.     }
  1389.     if (code == KRB5_CC_END) {
  1390. if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  1391.             debug(F101,"ck_krb5_tkt_flags while finishing ticket retrieval",
  1392.                    "",code);
  1393.             goto exit_k5_get_tkt;
  1394. }
  1395. flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
  1396. if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1397.             debug(F101,"ck_krb5_tkt_flags while closing ccache",
  1398.                    "",code);
  1399.             goto exit_k5_get_tkt;
  1400. }
  1401.     } else {
  1402.         debug(F101,"ck_krb5_tkt_flags while retrieving a ticket","",code);
  1403.         goto exit_k5_get_tkt;
  1404.     }
  1405.   exit_k5_get_tkt:
  1406.     krb5_free_principal(kcontext,princ);
  1407.     krb5_free_unparsed_name(kcontext,defname);
  1408.     krb5_cc_close(kcontext,cache);
  1409.     krb5_free_context(kcontext);
  1410.     return(flag_str);
  1411. #else /* KRB5 */
  1412.     return("");
  1413. #endif /* KRB5 */
  1414. }
  1415. int
  1416. #ifdef CK_ANSIC
  1417. ck_krb5_tkt_isvalid(char * cc_name, char * tktname)
  1418. #else
  1419. ck_krb5_tkt_isvalid(cc_name,tktname) char * cc_name; char * tktname;
  1420. #endif
  1421. {
  1422. #ifdef KRB5
  1423.     krb5_context kcontext=NULL;
  1424.     krb5_error_code retval;
  1425.     krb5_ccache cache = NULL;
  1426.     krb5_cc_cursor cur;
  1427.     krb5_creds creds;
  1428.     krb5_principal princ=NULL;
  1429.     krb5_flags flags=0;
  1430.     krb5_error_code code=0;
  1431. #ifdef CHECKADDRS
  1432.     krb5_address ** myAddrs=NULL;
  1433.     krb5_address ** p=NULL;
  1434.     BOOL         Addrfound = FALSE;
  1435. #endif /*CHECKADDRS*/
  1436.     if ( !ck_krb5_is_installed() )
  1437.         return(-1);
  1438.     retval = krb5_init_context(&kcontext);
  1439.     if (retval) {
  1440.         debug(F101,"ck_krb5_tkt_isvalid while initializing krb5","",retval);
  1441.         return(-1);
  1442.     }
  1443.     code = k5_get_ccache(kcontext,&cache,cc_name);
  1444.     if (code != 0) {
  1445.         debug(F111,"ck_krb5_tkt_isvalid while getting ccache",
  1446.                error_message(code),code);
  1447.         goto exit_k5_get_tkt;
  1448.     }
  1449.     flags = 0; /* turns off OPENCLOSE mode */
  1450.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1451. if (code == ENOENT) {
  1452.             debug(F111,"ck_krb5_tkt_isvalid (ticket cache)",
  1453.                    krb5_cc_get_name(kcontext, cache),code);
  1454. } else {
  1455.             debug(F111,
  1456. "ck_krb5_tkt_isvalid while setting cache flags (ticket cache)",
  1457.                   krb5_cc_get_name(kcontext, cache),code);
  1458. }
  1459.         retval = -1;
  1460.         goto exit_k5_get_tkt;
  1461.     }
  1462.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  1463.         debug(F101,"ck_krb5_tkt_isvalid while retrieving principal name",
  1464.                "",code);
  1465.         retval = -1;
  1466.         goto exit_k5_get_tkt;
  1467.     }
  1468.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  1469.         debug(F101,"ck_krb5_tkt_isvalid while unparsing principal name",
  1470.                "",code);
  1471.         retval = -1;
  1472.         goto exit_k5_get_tkt;
  1473.     }
  1474.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  1475.         debug(F101,"ck_krb5_tkt_isvalid while starting to retrieve tickets",
  1476.                "",code);
  1477.         retval = -1;
  1478.         goto exit_k5_get_tkt;
  1479.     }
  1480.     if ((code = krb5_timeofday(kcontext, &now))) {
  1481.         if (!status_only)
  1482.             debug(F101,"ck_krb5_tkt_isvalid while getting time of day.",
  1483.                    "",code);
  1484.         retval = -1;
  1485.         goto exit_k5_get_tkt;
  1486.     }
  1487.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  1488.         char *sname=NULL;
  1489.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  1490.         if (retval) {
  1491.             debug(F101,
  1492.   "ck_krb5_tkt_isvalid while unparsing server name","",retval);
  1493.             retval = -1;
  1494.             krb5_free_cred_contents(kcontext, &creds);
  1495.             goto exit_k5_get_tkt;
  1496.         }
  1497.         if ( !strcmp(sname,tktname) ) {
  1498.             /* we found the ticket we are looking for */
  1499.             /* We add a 5 minutes fudge factor to compensate for potential */
  1500.             /* clock skew errors between the KDC and K95's host OS         */
  1501.             retval = (creds.times.starttime &&
  1502.                        now >= (creds.times.starttime-300) &&
  1503.                        now < creds.times.endtime &&
  1504.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  1505. #ifdef CHECKADDRS
  1506.             if ( retval && krb5_checkaddrs ) {
  1507.                 /* if we think it is valid, then lets check the IP Addresses */
  1508.                 /* to make sure it is valid for our current connection.      */
  1509.                 /* Also make sure it's for the correct IP address */
  1510. retval = krb5_os_localaddr(kcontext, &myAddrs);
  1511.                 if (retval) {
  1512.                     com_err(NULL, retval, "retrieving my IP address");
  1513.                     krb5_free_cred_contents(kcontext, &creds);
  1514.                     code = KRB5_CC_END;
  1515.                     retval = -1;
  1516.                     break;
  1517.                 }
  1518.      /* See if any of our addresses match any in cached credentials */
  1519.                 for (Addrfound=FALSE, p=myAddrs;
  1520.      (Addrfound==FALSE) && (*p);
  1521.      p++
  1522.      ) {
  1523.                     if (krb5_address_search(kcontext, *p, creds.addresses)) {
  1524. Addrfound = TRUE;
  1525.                     }
  1526.                 }
  1527.                 krb5_free_addresses(k5_context, myAddrs);
  1528.                 if (Addrfound) {
  1529.                     krb5_free_cred_contents(kcontext, &creds);
  1530.                     code = KRB5_CC_END;
  1531.                     retval = 1;
  1532.                     break;
  1533.                 } else {
  1534.                     krb5_free_cred_contents(kcontext, &creds);
  1535.                     code = KRB5_CC_END;
  1536.                     retval = 0;
  1537.                     break;
  1538.                 }
  1539.             }
  1540. #endif /* CHECKADDRS */
  1541.             krb5_free_cred_contents(kcontext, &creds);
  1542.             code = KRB5_CC_END;
  1543.             break;
  1544.         }
  1545. krb5_free_cred_contents(kcontext, &creds);
  1546.     }
  1547.     if (code == KRB5_CC_END) {
  1548. if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  1549.             debug(F101,"ck_krb5_tkt_isvalid while finishing ticket retrieval",
  1550.                    "",code);
  1551.             retval = -1;
  1552.             goto exit_k5_get_tkt;
  1553. }
  1554. flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
  1555. if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1556.             debug(F101,"ck_krb5_tkt_isvalid while closing ccache",
  1557.                    "",code);
  1558.             retval = -1;
  1559.             goto exit_k5_get_tkt;
  1560. }
  1561.     } else {
  1562.         debug(F101,"ck_krb5_tkt_isvalid while retrieving a ticket","",code);
  1563.         retval = -1;
  1564.         goto exit_k5_get_tkt;
  1565.     }
  1566.   exit_k5_get_tkt:
  1567.     krb5_free_principal(kcontext,princ);
  1568.     krb5_free_unparsed_name(kcontext,defname);
  1569.     krb5_cc_close(kcontext,cache);
  1570.     krb5_free_context(kcontext);
  1571.     return(retval);
  1572. #else /* KRB5 */
  1573.     return(-1);
  1574. #endif /* KRB5 */
  1575. }
  1576. int
  1577. #ifdef CK_ANSIC
  1578. ck_krb5_is_tgt_valid(VOID)
  1579. #else
  1580. ck_krb5_is_tgt_valid()
  1581. #endif
  1582. {
  1583. #ifdef KRB5
  1584.     char tgt[256];
  1585.     char * s;
  1586.     int rc = 0;
  1587.     s = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  1588.     sprintf(tgt,"krbtgt/%s@%s",s,s);
  1589.     rc = ck_krb5_tkt_isvalid(krb5_d_cc,tgt);
  1590.     debug(F111,"ck_krb5_is_tgt_valid",tgt,rc);
  1591.     return(rc>0);
  1592. #else /* KRB5 */
  1593.     return(0);
  1594. #endif /* KRB5 */
  1595. }
  1596. int
  1597. #ifdef CK_ANSIC
  1598. ck_krb5_tkt_time(char * cc_name, char * tktname)
  1599. #else
  1600. ck_krb5_tkt_time(cc_name, tktname) char * cc_name; char * tktname;
  1601. #endif
  1602. {
  1603. #ifdef KRB5
  1604.     krb5_context kcontext;
  1605.     krb5_error_code retval;
  1606.     krb5_ccache cache = NULL;
  1607.     krb5_cc_cursor cur;
  1608.     krb5_creds creds;
  1609.     krb5_principal princ=NULL;
  1610.     krb5_flags flags=0;
  1611.     krb5_error_code code=0;
  1612.     if ( !ck_krb5_is_installed() )
  1613.         return(-1);
  1614.     retval = krb5_init_context(&kcontext);
  1615.     if (retval) {
  1616.         debug(F101,"ck_krb5_list_creds while initializing krb5","",retval);
  1617.         return(-1);
  1618.     }
  1619.     code = k5_get_ccache(kcontext,&cache,cc_name);
  1620.     if (code != 0) {
  1621.         debug(F111,"ck_krb5_tkt_time while getting ccache",
  1622.                error_message(code),code);
  1623.         retval = -1;
  1624.         goto exit_k5_get_tkt;
  1625.     }
  1626.     flags = 0; /* turns off OPENCLOSE mode */
  1627.     if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1628. if (code == ENOENT) {
  1629.             debug(F111,"ck_krb5_list_creds (ticket cache)",
  1630.                    krb5_cc_get_name(kcontext, cache),code);
  1631. } else {
  1632.             debug(F111,
  1633.  "ck_krb5_list_creds while setting cache flags (ticket cache)",
  1634.                   krb5_cc_get_name(kcontext, cache),code);
  1635. }
  1636.         retval = -1;
  1637.         goto exit_k5_get_tkt;
  1638.     }
  1639.     if ((code = krb5_cc_get_principal(kcontext, cache, &princ))) {
  1640.         debug(F101,"ck_krb5_list_creds while retrieving principal name",
  1641.                "",code);
  1642.         retval = -1;
  1643.         goto exit_k5_get_tkt;
  1644.     }
  1645.     if ((code = krb5_unparse_name(kcontext, princ, &defname))) {
  1646.         debug(F101,"ck_krb5_list_creds while unparsing principal name",
  1647.                "",code);
  1648.         retval = -1;
  1649.         goto exit_k5_get_tkt;
  1650.     }
  1651.     if ((code = krb5_cc_start_seq_get(kcontext, cache, &cur))) {
  1652.         debug(F101,"ck_krb5_list_creds while starting to retrieve tickets",
  1653.                "",code);
  1654.         retval = -1;
  1655.         goto exit_k5_get_tkt;
  1656.     }
  1657.     if ((code = krb5_timeofday(kcontext, &now))) {
  1658.         if (!status_only)
  1659.             debug(F101,"ck_krb5_list_creds while getting time of day.",
  1660.                    "",code);
  1661.         krb5_free_context(kcontext);
  1662.         return(-1);
  1663.     }
  1664.     while (!(code = krb5_cc_next_cred(kcontext, cache, &cur, &creds))) {
  1665.         char *sname=NULL;
  1666.         retval = krb5_unparse_name(kcontext, creds.server, &sname);
  1667.         if (retval) {
  1668.             debug(F101,
  1669.   "ck_krb5_list_creds while unparsing server name","",retval);
  1670.             retval = -1;
  1671.             krb5_free_cred_contents(kcontext, &creds);
  1672.             goto exit_k5_get_tkt;
  1673.         }
  1674.         if ( !strcmp(sname,tktname) ) {
  1675.             /* we found the ticket we are looking for */
  1676.             int valid = (creds.times.starttime &&
  1677.                        now > creds.times.starttime &&
  1678.                        now < creds.times.endtime &&
  1679.                        !(creds.ticket_flags & TKT_FLG_INVALID));
  1680.             if ( valid ) {
  1681.                 retval = creds.times.endtime - now;
  1682.             }
  1683.             else
  1684.                 retval = 0;
  1685.             krb5_free_cred_contents(kcontext, &creds);
  1686.             code = KRB5_CC_END;
  1687.             break;
  1688.         }
  1689. krb5_free_cred_contents(kcontext, &creds);
  1690.     }
  1691.     if (code == KRB5_CC_END) {
  1692. if ((code = krb5_cc_end_seq_get(kcontext, cache, &cur))) {
  1693.             debug(F101,"ck_krb5_list_creds while finishing ticket retrieval",
  1694.                    "",code);
  1695.             retval = -1;
  1696.             goto exit_k5_get_tkt;
  1697. }
  1698. flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */
  1699. if ((code = krb5_cc_set_flags(kcontext, cache, flags))) {
  1700.             debug(F101,"ck_krb5_list_creds while closing ccache",
  1701.                    "",code);
  1702.             retval = -1;
  1703.             goto exit_k5_get_tkt;
  1704. }
  1705.     } else {
  1706.         debug(F101,"ck_krb5_list_creds while retrieving a ticket","",code);
  1707.         retval = -1;
  1708.         goto exit_k5_get_tkt;
  1709.     }
  1710.   exit_k5_get_tkt:
  1711.     krb5_free_principal(kcontext,princ);
  1712.     krb5_free_unparsed_name(kcontext,defname);
  1713.     krb5_cc_close(kcontext,cache);
  1714.     krb5_free_context(kcontext);
  1715.     return(retval);
  1716. #else /* KRB5 */
  1717.     return(-1);
  1718. #endif /* KRB5 */
  1719. }
  1720. char *
  1721. #ifdef CK_ANSIC
  1722. ck_krb5_get_cc_name(void)
  1723. #else
  1724. ck_krb5_get_cc_name()
  1725. #endif
  1726. {
  1727. #ifdef KRB5
  1728.     static char cc_name[CKMAXPATH+1]="";
  1729.     krb5_context kcontext = NULL;
  1730.     krb5_ccache ccache = NULL;
  1731.     krb5_error_code code;
  1732.     char * p=NULL;
  1733.     cc_name[0] = '';
  1734.     if ( !ck_krb5_is_installed() )
  1735.         return(cc_name);
  1736.     p = getenv("KRB5CCNAME");
  1737.     if ( !p ) {
  1738.         code = krb5_init_context(&kcontext);
  1739.         if (code) {
  1740.             com_err("ck_krb5_get_cc_name",code,"while init_context");
  1741.             return(cc_name);
  1742.         }
  1743.         if ((code = krb5_cc_default(kcontext, &ccache))) {
  1744.             com_err("ck_krb5_get_cc_name",code,"while getting default ccache");
  1745.             goto exit_k5_get_cc;
  1746.         }
  1747.         sprintf(cc_name,"%s:%s",krb5_cc_get_type(kcontext,ccache),
  1748.                  krb5_cc_get_name(kcontext,ccache));
  1749.     } else {
  1750.         ckstrncpy(cc_name,p,CKMAXPATH);
  1751.     }
  1752.     if ( !strncmp("FILE:",cc_name,5) ) {
  1753.         for ( p=cc_name; *p ; p++ )
  1754.             if ( *p == '\' ) *p = '/';
  1755.     }
  1756.   exit_k5_get_cc:
  1757.     if ( ccache )
  1758.         krb5_cc_close(kcontext,ccache);
  1759.     if ( kcontext )
  1760.         krb5_free_context(kcontext);
  1761.     return(cc_name);
  1762. #else /* KRB5 */
  1763.     return("");
  1764. #endif /* KRB5 */
  1765. }
  1766. char *
  1767. #ifdef CK_ANSIC
  1768. ck_krb5_getrealm(char * cc_name)
  1769. #else
  1770. ck_krb5_getrealm(cc_name) char * cc_name;
  1771. #endif
  1772. {
  1773. #ifdef KRB5
  1774.     static char realm[256]="";
  1775.     krb5_context kcontext;
  1776.     krb5_ccache ccache = NULL;
  1777.     krb5_error_code code;
  1778.     krb5_principal me;
  1779.     realm[0] = '';
  1780.     if ( !ck_krb5_is_installed() )
  1781.         return(realm);
  1782.     code = krb5_init_context(&kcontext);
  1783.     if (code) {
  1784.         return(realm);
  1785.     }
  1786.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  1787.     if (code != 0) {
  1788.         goto exit_k5_getrealm;
  1789.     }
  1790.     if ((code = krb5_parse_name(kcontext, "foo", &me))) {
  1791.         goto exit_k5_getrealm;
  1792.     }
  1793.     memcpy(realm,krb5_princ_realm(kcontext, me)->data,
  1794.             krb5_princ_realm(kcontext, me)->length);
  1795.     realm[krb5_princ_realm(kcontext, me)->length]='';
  1796.   exit_k5_getrealm:
  1797.     if ( ccache )
  1798.         krb5_cc_close(kcontext,ccache);
  1799.     if (kcontext)
  1800.         krb5_free_context(kcontext);
  1801.     return(realm);
  1802. #else /* KRB5 */
  1803.     return("");
  1804. #endif /* KRB5 */
  1805. }
  1806. char *
  1807. #ifdef CK_ANSIC
  1808. ck_krb5_getprincipal(char * cc_name)
  1809. #else
  1810. ck_krb5_getprincipal(cc_name) char * cc_name;
  1811. #endif
  1812. {
  1813. #ifdef KRB5
  1814.     static char principal[UIDBUFLEN+1]="";
  1815.     krb5_context kcontext;
  1816.     krb5_ccache ccache = NULL;
  1817.     krb5_error_code code;
  1818.     krb5_principal me;
  1819.     char * p=NULL;
  1820.     int i;
  1821.     principal[0] = '';
  1822.     if ( !ck_krb5_is_installed() )
  1823.         return(principal);
  1824.     code = krb5_init_context(&kcontext);
  1825.     if (code) {
  1826.         return(principal);
  1827.     }
  1828.     code = k5_get_ccache(kcontext,&ccache,cc_name);
  1829.     if (code != 0) {
  1830.         goto exit_k5_getprincipal;
  1831.     }
  1832.     if ((code = krb5_cc_get_principal(kcontext, ccache, &me))) {
  1833.         goto exit_k5_getprincipal;
  1834.     }
  1835.     if ((code = krb5_unparse_name (kcontext, me, &p))) {
  1836.         krb5_free_principal(kcontext,me);
  1837.         goto exit_k5_getprincipal;
  1838.     }
  1839.     ckstrncpy(principal,p,UIDBUFLEN);
  1840.     i = ckindex("@",principal,0,0,0);
  1841.     if (i)
  1842.       principal[i-1] = '';
  1843.     krb5_free_unparsed_name(kcontext,p);
  1844.   exit_k5_getprincipal:
  1845.     if ( ccache )
  1846.         krb5_cc_close(kcontext,ccache);
  1847.     if (kcontext)
  1848.         krb5_free_context(kcontext);
  1849.     return(principal);
  1850. #else /* KRB5 */
  1851.     return("");
  1852. #endif /* KRB5 */
  1853. }
  1854. #ifndef CRYPT_DLL
  1855. int
  1856. ck_get_crypt_table(struct keytab ** pTable, int * pN)
  1857. {
  1858. #ifdef CK_ENCRYPTION
  1859.     return(get_crypt_table(pTable, pN));
  1860. #else /* ENCRYPTION */
  1861.     int i=0;
  1862. #ifndef OS2
  1863.     char * tmpstring = NULL;
  1864. #endif /* OS2 */
  1865.     if ( *pTable )
  1866.     {
  1867.         for ( i=0 ; i < *pN ; i++ )
  1868.             free( (*pTable)[i].kwd ) ;
  1869.         free ( *pTable )  ;
  1870.     }
  1871.     *pTable = NULL;
  1872.     *pN = 0;
  1873.     *pTable = malloc( sizeof(struct keytab) * 2 ) ;
  1874.     if ( !(*pTable) )
  1875.         return(0);
  1876. #ifdef OS2
  1877.     (*pTable)[0].kwd =strdup("automatic");
  1878. #else /* OS2 */
  1879.     makestr(&tmpstring,"automatic");
  1880.     (*pTable)[0].kwd = tmpstring;
  1881.     tmpstring = NULL;
  1882. #endif /* OS2 */
  1883.     (*pTable)[0].kwval = ENCTYPE_ANY;
  1884.     (*pTable)[0].flgs = 0;
  1885. #ifdef OS2
  1886.     (*pTable)[1].kwd =strdup("none");
  1887. #else /* OS2 */
  1888.     makestr(&tmpstring,"none");
  1889.     (*pTable)[1].kwd = tmpstring;
  1890.     tmpstring = NULL;
  1891. #endif /* OS2 */
  1892.     (*pTable)[1].kwval = 999;
  1893.     (*pTable)[1].flgs = 0;
  1894.     (*pN) = 2;
  1895.     return(2);
  1896. #endif /* ENCRYPTION */
  1897. }
  1898. VOID
  1899. ck_encrypt_send_support()
  1900. {
  1901. #ifdef CK_ENCRYPTION
  1902.     encrypt_send_support();
  1903. #endif /* ENCRYPTION */
  1904. }
  1905. #endif /* CRYPT_DLL */
  1906. /*
  1907.  *
  1908.  * Kstream
  1909.  *
  1910.  * Emulates the kstream package in Kerberos 4
  1911.  *
  1912.  */
  1913. int
  1914. kstream_destroy()
  1915. {
  1916.     if (g_kstream != NULL) {
  1917.         auth_destroy();                       /* Destroy authorizing */
  1918.         free(g_kstream);
  1919.         g_kstream=NULL;
  1920.     }
  1921.     return 0;
  1922. }
  1923. VOID
  1924. #ifdef CK_ANSIC
  1925. kstream_set_buffer_mode(int mode)
  1926. #else
  1927. kstream_set_buffer_mode(mode) int mode;
  1928. #endif
  1929. {
  1930. }
  1931. int
  1932. #ifdef CK_ANSIC
  1933. kstream_create_from_fd(int fd,
  1934.        const struct kstream_crypt_ctl_block *ctl,
  1935.        kstream_ptr data)
  1936. #else
  1937. kstream_create_from_fd(fd,ctl,data)
  1938.     int fd; const struct kstream_crypt_ctl_block *ctl; kstream_ptr data;
  1939. #endif
  1940. {
  1941.     int n;
  1942.     g_kstream = malloc(sizeof(struct kstream_int));
  1943.     if (g_kstream == NULL)
  1944.         return 0;
  1945.     g_kstream->fd = fd;
  1946.     n = auth_init(g_kstream);                   /* Initialize authorizing */
  1947.     if (n) {
  1948.         free(g_kstream);
  1949.         g_kstream = NULL;
  1950.         return 0;
  1951.     }
  1952.     g_kstream->encrypt = NULL;
  1953.     g_kstream->decrypt = NULL;
  1954.     g_kstream->encrypt_type = ENCTYPE_ANY;
  1955.     g_kstream->decrypt_type = ENCTYPE_ANY;
  1956.     return 1;
  1957. }
  1958. #ifdef RLOGCODE
  1959. #ifdef CK_KERBEROS
  1960. int
  1961. #ifdef CK_ANSIC
  1962. ck_krb_rlogin(CHAR * hostname, int port,
  1963.                CHAR * localuser, CHAR * remoteuser, CHAR * term_speed,
  1964.                struct sockaddr_in * l_addr, struct sockaddr_in * r_addr,
  1965.                int kversion, int encrypt_flag)
  1966. #else /* CK_ANSIC */
  1967. ck_krb_rlogin(hostname, port,
  1968.                localuser, remoteuser, term_speed, l_addr, r_addr, encrypt_flag)
  1969.     CHAR * hostname; int port;
  1970.     CHAR * localuser; CHAR * remoteuser; CHAR * term_speed;
  1971.     struct sockaddr_in * l_addr; struct sockaddr_in * r_addr;
  1972.     int kversion; int encrypt_flag;
  1973. #endif /* CK_ANSIC */
  1974. {
  1975.     unsigned long status;
  1976.     char * realm=NULL;
  1977.     extern int ttyfd;
  1978.     int c;
  1979.     long msglen;
  1980.     debug(F111,"ck_krb_rlogin",hostname,port);
  1981.     if ( kversion == 4 && !ck_krb4_is_installed() ) {
  1982.         printf("?Kerberos 4 is not installedrn");
  1983.         return(-1);
  1984.     } else if ( kversion == 5 && !ck_krb5_is_installed() ) {
  1985.         printf("?Kerberos 5 is not installedrn");
  1986.         return(-1);
  1987.     }
  1988.     if ( encrypt_flag && !ck_crypt_is_installed() ) {
  1989.         printf("?Encryption is not installedrn");
  1990.         return(-1);
  1991.     }
  1992.     if ( kversion == 5 ) {
  1993. #ifdef KRB5
  1994.         krb5_flags authopts=0;
  1995.         krb5_ccache ccache=NULL;
  1996.         char *cksumbuf=NULL;
  1997.         char *service=NULL;
  1998.         krb5_data cksumdat;
  1999.         krb5_creds *get_cred = 0;
  2000.         krb5_error_code status;
  2001.         krb5_error *error = 0;
  2002.         krb5_ap_rep_enc_part *rep_ret = NULL;
  2003.         krb5_data outbuf;
  2004.         krb5_auth_context auth_context = NULL;
  2005.         int rc;
  2006.         krb5_int32 seqno=0;
  2007.         krb5_int32 server_seqno=0;
  2008.         char ** realmlist=NULL;
  2009.         debug(F100,"ck_krb_rlogin version 5","",0);
  2010.         if ((cksumbuf = malloc(strlen(term_speed)+strlen(remoteuser)+64)) == 0)
  2011.   {
  2012.       printf("Unable to allocate memory for checksum buffer.rn");
  2013.       return(-1);
  2014.   }
  2015.         sprintf(cksumbuf, "%u:", (unsigned short) ntohs(port));
  2016.         strcat(cksumbuf, term_speed);
  2017.         strcat(cksumbuf, remoteuser);
  2018.         cksumdat.data = cksumbuf;
  2019.         cksumdat.length = strlen(cksumbuf);
  2020.         status = krb5_init_context(&k5_context);
  2021.         if (status) {
  2022.             return(-1);
  2023.         }
  2024.         desinbuf.data = des_inbuf;
  2025.         desoutbuf.data = des_outpkt+4; /* Set up des buffers */
  2026.         authopts = AP_OPTS_MUTUAL_REQUIRED;
  2027.         rc = k5_get_ccache(k5_context,&ccache,NULL);
  2028.         if (rc != 0) {
  2029.             com_err(NULL, rc, "while getting ccache.");
  2030.             return(0);
  2031.         }
  2032.         service = krb5_d_srv ? krb5_d_srv : KRB5_SERVICE_NAME;
  2033.         if (!(get_cred = (krb5_creds *)calloc(1, sizeof(krb5_creds)))) {
  2034.             printf("kcmd: no memoryrn");
  2035.             return(-1);
  2036.         }
  2037.         status = krb5_sname_to_principal(k5_context, hostname, service,
  2038.                                           KRB5_NT_SRV_HST, &get_cred->server);
  2039.         if (status) {
  2040.     printf("kcmd: krb5_sname_to_principal failed: %srn",
  2041.                      error_message(status));
  2042.     return(-1);
  2043.         }
  2044.         krb5_get_host_realm(k5_context,hostname,&realmlist);
  2045.         if (realmlist && realmlist[0]) {
  2046.             makestr(&realm,realmlist[0]);
  2047.             krb5_free_host_realm(k5_context,realmlist);
  2048.             realmlist = NULL;
  2049.         }
  2050.         if (!realm || !realm[0] )
  2051.             realm = krb5_d_realm ? krb5_d_realm : ck_krb5_getrealm(krb5_d_cc);
  2052.         if (realm && *realm) {
  2053.             free(krb5_princ_realm(k5_context,get_cred->server)->data);
  2054.             krb5_princ_set_realm_length(k5_context,
  2055. get_cred->server,
  2056. strlen(realm)
  2057. );
  2058.             krb5_princ_set_realm_data(k5_context,
  2059.       get_cred->server,
  2060.       strdup(realm)
  2061.       );
  2062.         }
  2063.         ttoc(0);
  2064.         if (status = krb5_cc_get_principal(k5_context,
  2065.    ccache,
  2066.    &get_cred->client)
  2067.     ) {
  2068.             (void) krb5_cc_close(k5_context, ccache);
  2069.             krb5_free_creds(k5_context, get_cred);
  2070.             goto bad2;
  2071.         }
  2072.         /* Get ticket from credentials cache or kdc */
  2073.         status = krb5_get_credentials(k5_context,
  2074.       0,
  2075.       ccache,
  2076.       get_cred,
  2077.       &ret_cred
  2078.       );
  2079.         krb5_free_creds(k5_context, get_cred);
  2080.         get_cred = NULL;
  2081.         (void) krb5_cc_close(k5_context, ccache);
  2082.         if (status)
  2083.             goto bad2;
  2084.         if (krb5_auth_con_init(k5_context, &auth_context))
  2085.             goto bad2;
  2086.         if (krb5_auth_con_setflags(k5_context, auth_context,
  2087.                                     KRB5_AUTH_CONTEXT_RET_TIME))
  2088.             goto bad2;
  2089.         /* Only need local address for mk_cred() to send to krlogind */
  2090.         if (status = krb5_auth_con_genaddrs(k5_context,
  2091.     auth_context,
  2092.     ttyfd,
  2093. KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR
  2094.     )
  2095.     )
  2096.             goto bad2;
  2097.         /* call Kerberos library routine to obtain an authenticator,
  2098.            pass it over the socket to the server, and obtain mutual
  2099.            authentication.
  2100.          */
  2101.         status = krb5_sendauth(k5_context,
  2102.        &auth_context,
  2103.        (krb5_pointer) &ttyfd,
  2104.        "KCMDV0.1",
  2105.        ret_cred->client,
  2106.        ret_cred->server,
  2107.                                 authopts,
  2108.        &cksumdat,
  2109.        ret_cred,
  2110.        0,
  2111.        &error,
  2112.        &rep_ret,
  2113.        NULL
  2114.        );
  2115.         free(cksumdat.data);
  2116.         if (status) {
  2117.     printf("Couldn't authenticate to server: %srn",
  2118.                      error_message(status));
  2119.             if (error) {
  2120.                 printf("Server returned error code %d (%s)rn",
  2121.                         error->error,
  2122.                         error_message(ERROR_TABLE_BASE_krb5 + error->error));
  2123.                 if (error->text.length) {
  2124.                     printf("Error text sent from server: %srn",
  2125.                              error->text.data);
  2126.                 }
  2127.                 krb5_free_error(k5_context, error);
  2128.                 error = 0;
  2129.             }
  2130.             goto bad2;
  2131.         }
  2132.         if (rep_ret) {
  2133.             server_seqno = rep_ret->seq_number;
  2134.             krb5_free_ap_rep_enc_part(k5_context, rep_ret);
  2135.         }
  2136.         (void) ttol(remoteuser, strlen(remoteuser)+1);
  2137.         (void) ttol(term_speed, strlen(term_speed)+1);
  2138.         (void) ttol(localuser, strlen(localuser)+1);
  2139.         if (forward_flag) {   /* Forward credentials (global) */
  2140.             if (status = krb5_fwd_tgt_creds( k5_context,
  2141.                                              auth_context,
  2142.                                              hostname,
  2143.                                              ret_cred->client,
  2144.                                              ret_cred->server,
  2145.                                              0,
  2146.                                              (forwardable_flag ?
  2147.                                                OPTS_FORWARDABLE_CREDS :
  2148.                                                0),
  2149.                                              &outbuf
  2150.                                              )
  2151.                  )
  2152.             {
  2153.                 printf("Error forwarding credentials: %srn",
  2154.                          error_message(status));
  2155.                 goto bad2;
  2156.             }
  2157.             /* Send forwarded credentials */
  2158. #ifdef COMMENT
  2159.             if (status = krb5_write_message(k5_context,
  2160.     (krb5_pointer)&ttyfd,
  2161.     &outbuf
  2162.     )
  2163. )
  2164.                 goto bad2;
  2165. #else /* COMMENT */
  2166.             msglen = htonl(outbuf.length);
  2167.             if (ttol((CHAR *)&msglen,4) != 4) {
  2168.                 status = -1;
  2169.                 goto bad2;
  2170.             }
  2171.             if ( outbuf.length ) {
  2172.                 if (ttol(outbuf.data,outbuf.length) != outbuf.length) {
  2173.                     status = -1;
  2174.                     goto bad2;
  2175.                 }
  2176.             }
  2177. #endif /* COMMENT */
  2178.         }
  2179.         else { /* Dummy write to signal no forwarding */
  2180. #ifdef COMMENT
  2181.             outbuf.length = 0;
  2182.             if (status = krb5_write_message(k5_context,
  2183.     (krb5_pointer)&ttyfd,
  2184.     &outbuf
  2185.     )
  2186. )
  2187.                 goto bad2;
  2188. #else /* COMMENT */
  2189.             msglen = htonl(0);
  2190.             if (ttol((CHAR *)&msglen,4) != 4) {
  2191.                 status = -1;
  2192.                 goto bad2;
  2193.             }
  2194. #endif /* COMMENT */
  2195.         }
  2196.         if ((c = ttinc(0)) < 0) {
  2197.             if (c==-1) {
  2198.                 perror(hostname);
  2199.             } else {
  2200.                 printf("kcmd: bad connection with remote hostrn");
  2201.             }
  2202.             status = -1;
  2203.             goto bad2;
  2204.         }
  2205.         if (c != 0) {
  2206.             while ((c = ttinc(1)) >= 0) {
  2207.                 (void) printf("%c",c);
  2208.                 if (c == 'n')
  2209.                     break;
  2210.             }
  2211.             status = -1;
  2212.             goto bad2;
  2213.         }
  2214. #ifdef MIT_CURRENT
  2215.         /* This code comes from the new MIT krb-current sources which is not */
  2216.         /* supported in the krb-1.0.5 distribution upon which all of the     */
  2217.         /* shipping libraries are based.                                     */
  2218.         if ( status == 0 ) {        /* success */
  2219.             krb5_boolean similar;
  2220.             rcmd_stream_init_krb5(&ret_cred->keyblock, encrypt_flag, 1);
  2221.             if (status = krb5_c_enctype_compare( k5_context,
  2222.                                                  ENCTYPE_DES_CBC_CRC,
  2223.                                                  ret_cred->keyblock.enctype,
  2224.                                                  &similar)) {
  2225.                 krb5_free_creds(k5_context, ret_cred);
  2226.                 ret_cred = NULL;
  2227.                 return(-1);
  2228.             }
  2229.             /* what is do_inband for? */
  2230.             if (!similar) {
  2231.                 do_inband = 1;
  2232.             }
  2233.         }
  2234. #else /* MIT_CURRENT */
  2235.         if ( status ) {
  2236.             /* should check for KDC_PR_UNKNOWN, NO_TKT_FILE here -- XXX */
  2237.             if (status != -1)
  2238.                 printf("[e]klogin to host %s failed - %srn",hostname,
  2239.                          error_message(status));
  2240.             goto bad2;
  2241.         }
  2242.         if ( encrypt_flag ) {
  2243.             /* if we are encrypting we need to setup the encryption */
  2244.             /* routines.                                            */
  2245.             /* setup eblock for des_read and write */
  2246.             krb5_use_enctype(k5_context, &eblock,ret_cred->keyblock.enctype);
  2247.             if (status = krb5_process_key(k5_context,
  2248.                                            &eblock,
  2249.                                            &ret_cred->keyblock
  2250.                                            )
  2251.                  ) {
  2252.                 printf("Cannot process session key : %s.rn",
  2253.                          error_message(status)
  2254.                          );
  2255.                 goto bad2;
  2256.             }
  2257.             rlog_encrypt = 1;
  2258.         }
  2259. #endif /* MIT_CURRENT */
  2260.         return (0);     /* success */
  2261.       bad2:
  2262.       bad:
  2263.         if (ret_cred) {
  2264.             krb5_free_creds(k5_context, ret_cred);
  2265.             ret_cred = NULL;
  2266.         }
  2267.         return (status);
  2268. #else /* KRB5 */
  2269.         return(-1);
  2270. #endif /* KRB5 */
  2271.     } else if (kversion == 4) {
  2272. #ifdef KRB4
  2273.         debug(F100,"ck_krb_rlogin version 4","",0);
  2274.         realm = (char *)krb_realmofhost(szHostName);
  2275.         if ((realm == NULL) || (realm[0] == '')) {
  2276.             realm = krb4_d_realm;
  2277.         }
  2278.         ttoc(0);        /* write a NUL */
  2279.         status = krb_sendauth(encrypt_flag?KOPT_DO_MUTUAL:0,
  2280.                                ttyfd,
  2281.                                &k4_auth,
  2282.                                krb4_d_srv ? krb4_d_srv : KRB4_SERVICE_NAME,
  2283.                                hostname,
  2284.                                realm,
  2285.                                (unsigned long) getpid(),
  2286.                                &k4_msg_data,
  2287.                                (CREDENTIALS *)&cred,
  2288. #ifdef CK_ENCRYPTION
  2289.                                &k4_sched,
  2290. #else /* ENCRYPTION */
  2291.                                NULL,
  2292. #endif /* ENCRYPTION */
  2293.                                l_addr,
  2294.                                r_addr,
  2295.                                "KCMDV0.1");
  2296.         debug(F111,"ck_krb_rlogin","krb_sendauth",status);
  2297.         if (status != KSUCCESS) {
  2298.             printf( "krb_sendauth failed: %srn",
  2299.     krb_get_err_text_entry(status)
  2300.     );
  2301.             return(-1);
  2302.         }
  2303.         ttol(remoteuser,strlen(remoteuser)+1);
  2304.         ttol(term_speed,strlen(term_speed)+1);
  2305.       reread:
  2306.         if ((c = ttinc(0)) < 0) {
  2307.             printf("rcmd: bad connection with remote hostrn");
  2308.             return(-1);
  2309.         }
  2310.         debug(F111,"ck_krb_rlogin","first byte",c);
  2311.         if (c != 0) {
  2312.             char *check = "ld.so: warning:";
  2313.             /* If rlogind was compiled on SunOS4, and it somehow
  2314.             got the shared library version numbers wrong, it
  2315.             may give an ld.so warning about an old version of a
  2316.             shared library.  Just ignore any such warning.
  2317.             Note that the warning is a characteristic of the
  2318.             server; we may not ourselves be running under
  2319.             SunOS4.  */
  2320.             if (c == 'l') {
  2321.                 char *p;
  2322.                 char cc;
  2323.                 p = &check[1];
  2324.                 while ((c = ttinc(0)) >= 0) {
  2325.                     if (*p == '') {
  2326.                         if (c == 'n')
  2327.                             break;
  2328.                     } else {
  2329.                         if (c != *p)
  2330.                             break;
  2331.                         ++p;
  2332.                     }
  2333.                 }
  2334.                 if (*p == '')
  2335.                     goto reread;
  2336.             }
  2337.             printf(check);
  2338.             while ((c = ttinc(1)) >= 0) {
  2339.                 printf("%c",c);
  2340.                 if (c == 'n')
  2341.                     break;
  2342.             }
  2343.             debug(F110,"ck_krb_rlogin","fatal error 1",0);
  2344.             return(-1);
  2345.         }
  2346. #ifdef CK_ENCRYPTION
  2347.         if ( encrypt_flag ) {
  2348.             /* if we are encrypting we need to setup the encryption */
  2349.             /* routines.                                            */
  2350.             des_key_sched(cred.session, k4_sched);
  2351.             rlog_encrypt = 1;
  2352.         }
  2353. #endif /* ENCRYPTION */
  2354. #else /* KRB4 */
  2355.         return(-1);
  2356. #endif /* KRB4 */
  2357.     }
  2358.     return(0); /* success */
  2359. }
  2360. #define SRAND srand
  2361. #define RAND rand
  2362. #define RAND_TYPE int
  2363. static long
  2364. random_confounder(size, fillin)
  2365. size_t size;
  2366. char * fillin;
  2367. {
  2368.     static int seeded = 0;
  2369.     register unsigned char *real_fill;
  2370.     RAND_TYPE rval;
  2371.     if (!seeded) {
  2372. /* time() defined in 4.12.2.4, but returns a time_t, which is an
  2373.    "arithmetic type" (4.12.1) */
  2374. rval = (RAND_TYPE) time(0);
  2375. SRAND(rval);
  2376. rval = RAND();
  2377. rval ^= getpid();
  2378. SRAND(rval);
  2379. seeded = 1;
  2380.     }
  2381.     real_fill = (unsigned char *)fillin;
  2382.     while (size > 0) {
  2383. rval = RAND();
  2384. *real_fill = rval & 0xff;
  2385. real_fill++;
  2386. size--;
  2387. if (size) {
  2388.     *real_fill = (rval >> 8) & 0xff;
  2389.     real_fill++;
  2390.     size--;
  2391. }
  2392.     }
  2393.     return 0;
  2394. }
  2395. #ifdef KRB5
  2396. int
  2397. krb5_des_avail(fd)
  2398.     int fd;
  2399. {
  2400.     return(nstored);
  2401. }
  2402. int
  2403. krb5_des_read(fd, buf, len)
  2404.      int fd;
  2405.      register char *buf;
  2406.      int len;
  2407. {
  2408.     int nreturned = 0;
  2409.     long net_len,rd_len;
  2410.     int cc;
  2411.     unsigned char len_buf[4];
  2412.     krb5_error_code status;
  2413.     unsigned char c;
  2414.     int gotzero = 0;
  2415.     debug(F111,"krb5_des_read","rlog_encrypt",rlog_encrypt);
  2416.     debug(F111,"krb5_des_read","len",len);
  2417.     if ( !rlog_encrypt ) {
  2418.         cc = krb5_net_read(k5_context, fd, buf, len);
  2419.         debug(F111,"krb5_des_read","chars read",cc);
  2420.         if ( cc < 0 )
  2421.             netclos();
  2422.         return(cc);
  2423.     }
  2424.     if (nstored >= len) {
  2425.         if ( buf ) {
  2426.             memcpy(buf, store_ptr, len);
  2427.             store_ptr += len;
  2428.             nstored -= len;
  2429.             return(len);
  2430.         } else
  2431.             return(0);
  2432.     } else if (nstored) {
  2433.         if ( buf ) {
  2434.             memcpy(buf, store_ptr, nstored);
  2435.             nreturned += nstored;
  2436.             buf += nstored;
  2437.             len -= nstored;
  2438.             nstored = 0;
  2439.         }
  2440.         else
  2441.             return(0);
  2442.     }
  2443.     /* See the comment in v4_des_read. */
  2444.     do {
  2445.         cc = krb5_net_read(k5_context, fd, &c, 1);
  2446.         /* we should check for non-blocking here, but we'd have
  2447.         to make it save partial reads as well. */
  2448.         if (cc <= 0) {
  2449.             return cc; /* read error */
  2450.         }
  2451.         if (cc == 1) {
  2452.             if (c == 0) gotzero = 1;
  2453.         }
  2454.     } while (!gotzero);
  2455.     if ((cc = krb5_net_read(k5_context, fd, &c, 1)) != 1) return 0;
  2456.     rd_len = c;
  2457.     if ((cc = krb5_net_read(k5_context, fd, &c, 1)) != 1) return 0;
  2458.     rd_len = (rd_len << 8) | c;
  2459.     if ((cc = krb5_net_read(k5_context, fd, &c, 1)) != 1) return 0;
  2460.     rd_len = (rd_len << 8) | c;
  2461.     net_len = krb5_encrypt_size(rd_len, eblock.crypto_entry);
  2462.     if ((net_len <= 0) || (net_len > sizeof(des_inbuf))) {
  2463. /* preposterous length; assume out-of-sync; only
  2464.    recourse is to close connection, so return 0 */
  2465. printf("Read size problem.rn");
  2466. return(0);
  2467.     }
  2468.     if ((cc = krb5_net_read(k5_context,
  2469.     fd,
  2470.     desinbuf.data,
  2471.     net_len)) != net_len )
  2472.     {
  2473. /* pipe must have closed, return 0 */
  2474. printf( "Read error: length received %d != expected %d.rn",
  2475. cc,
  2476. net_len
  2477. );
  2478. return(0);
  2479.     }
  2480.     /* decrypt info */
  2481.     if ((status = krb5_decrypt(k5_context, desinbuf.data,
  2482.       (krb5_pointer) storage,
  2483.       net_len,
  2484.       &eblock, 0))) {
  2485. printf("Cannot decrypt data from network: %srn",
  2486.                  error_message(status));
  2487. return(0);
  2488.     }
  2489.     store_ptr = storage;
  2490.     nstored = rd_len;
  2491.     if ( !buf ) {
  2492.         return(0);
  2493.     }
  2494.     if (nstored > len) {
  2495. memcpy(buf, store_ptr, len);
  2496. nreturned += len;
  2497. store_ptr += len;
  2498. nstored -= len;
  2499.     } else {
  2500. memcpy(buf, store_ptr, nstored);
  2501. nreturned += nstored;
  2502. nstored = 0;
  2503.     }
  2504.     return(nreturned);
  2505. }
  2506. int
  2507. krb5_des_write(fd, buf, len)
  2508.      int fd;
  2509.      char *buf;
  2510.      int len;
  2511. {
  2512.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  2513.     int cc;
  2514.     krb5_error_code status;
  2515.     debug(F111,"krb5_des_write","rlog_encrypt",rlog_encrypt);
  2516.     if ( !rlog_encrypt ) {
  2517.         cc = krb5_net_write(k5_context, fd, buf, len);
  2518.         debug(F111,"krb5_net_write","chars written",cc);
  2519.         return(cc != len ? -1 : len);
  2520.     }
  2521.     desoutbuf.length = krb5_encrypt_size(len,eblock.crypto_entry);
  2522.     if (desoutbuf.length > sizeof(des_outpkt)-4){
  2523.        printf("Write size problem.rn");
  2524. return(-1);
  2525.     }
  2526.     if ((status = krb5_encrypt(k5_context, (krb5_pointer)buf,
  2527.       desoutbuf.data,
  2528.       len,
  2529.       &eblock,
  2530.       0))){
  2531.        printf("Write encrypt problem: %s.rn",
  2532.                  error_message(status));
  2533. return(-1);
  2534.     }
  2535.     len_buf[0] = (len & 0xff000000) >> 24;
  2536.     len_buf[1] = (len & 0xff0000) >> 16;
  2537.     len_buf[2] = (len & 0xff00) >> 8;
  2538.     len_buf[3] = (len & 0xff);
  2539.     if (krb5_net_write(k5_context, fd, des_outpkt,desoutbuf.length+4)
  2540.          != desoutbuf.length+4){
  2541.         printf("Could not write out all datarn");
  2542. return(-1);
  2543.     }
  2544.     else return(len);
  2545. }
  2546. #endif /* KRB5 */
  2547. #ifdef KRB4
  2548. /*
  2549.  * Note that the encrypted rlogin packets take the form of a four-byte
  2550.  * length followed by encrypted data.  On writing the data out, a significant
  2551.  * performance penalty is suffered (at least one RTT per character, two if we
  2552.  * are waiting for a shell to echo) by writing the data separately from the
  2553.  * length.  So, unlike the input buffer, which just contains the output
  2554.  * data, the output buffer represents the entire packet.
  2555.  */
  2556. int
  2557. krb4_des_avail(fd)
  2558.     int fd;
  2559. {
  2560.     return(nstored);
  2561. }
  2562. int
  2563. krb4_des_read(fd, buf, len)
  2564. int fd;
  2565. register char *buf;
  2566. int len;
  2567. {
  2568.     int nreturned = 0;
  2569.     unsigned long net_len, rd_len;
  2570.     int cc;
  2571.     unsigned char c;
  2572.     int gotzero = 0;
  2573.     debug(F111,"krb4_des_read","rlog_encrypt",rlog_encrypt);
  2574.     debug(F111,"krb4_des_read","len",len);
  2575.     if ( !rlog_encrypt ) {
  2576.         cc = krb_net_read(fd, buf, len);
  2577.         debug(F111,"krb4_des_read","chars read",cc);
  2578.         if ( cc < 0 )
  2579.             netclos();
  2580.         return(cc);
  2581.     }
  2582.     if (nstored >= len) {
  2583.         if ( buf ) {
  2584.             debug(F111,"krb4_des_read (nstored >= len)","nstored",nstored);
  2585.             memcpy(buf, store_ptr, len);
  2586.             store_ptr += len;
  2587.             nstored -= len;
  2588.             return(len);
  2589.         } else
  2590.             return(0);
  2591.     } else if (nstored) {
  2592.         if ( buf ) {
  2593.             debug(F111,"krb4_des_read (nstored)","nstored",nstored);
  2594.             memcpy(buf, store_ptr, nstored);
  2595.             nreturned += nstored;
  2596.             buf += nstored;
  2597.             len -= nstored;
  2598.             nstored = 0;
  2599.         } else
  2600.             return(0);
  2601.     }
  2602.     /* We're fetching the length which is MSB first, and the MSB
  2603.     has to be zero unless the client is sending more than 2^24
  2604.     (16M) bytes in a single write (which is why this code is in
  2605.     rlogin but not rcp or rsh.) The only reasons we'd get something
  2606.     other than zero are:
  2607.     -- corruption of the tcp stream (which will show up when
  2608.     everything else is out of sync too)
  2609.     -- un-caught Berkeley-style "pseudo out-of-band data" which
  2610.     happens any time the user hits ^C twice.
  2611.     The latter is *very* common, as shown by an 'rlogin -x -d'
  2612.     using the CNS V4 rlogin.         Mark EIchin 1/95
  2613.     */
  2614.     debug(F110,"krb4_des_read",
  2615.   "about to call krb_net_read() this will block",
  2616.   0
  2617.   );
  2618.     do {
  2619.         cc = krb_net_read(fd, &c, 1);
  2620.         debug(F111,"krb_net_read","chars read",cc);
  2621.         if (cc <= 0) {
  2622.             netclos();
  2623.             return(-1);
  2624.         }
  2625.         if (cc != 1) return 0; /* read error */
  2626.         if (cc == 1) {
  2627.             if (c == 0) gotzero = 1;
  2628.         }
  2629.     } while (!gotzero);
  2630.     debug(F110,"krb4_des_read","gotzero",0);
  2631.     cc = krb_net_read(fd, &c, 1);
  2632.     debug(F111,"krb_net_read","chars read",cc);
  2633.     if (cc < 0) {
  2634.         netclos();
  2635.         return(-1);
  2636.     } else if ( cc != 1 )
  2637.         return(0);
  2638.     net_len = c;
  2639.     cc = krb_net_read(fd, &c, 1);
  2640.     debug(F111,"krb_net_read","chars read",cc);
  2641.     if (cc < 0) {
  2642.         netclos();
  2643.         return(-1);
  2644.     } else if ( cc != 1 )
  2645.         return(0);
  2646.     net_len = (net_len << 8) | c;
  2647.     debug(F111,"krb_net_read","chars read",cc);
  2648.     cc = krb_net_read(fd, &c, 1);
  2649.     if (cc < 0) {
  2650.         netclos();
  2651.         return(-1);
  2652.     } else if ( cc != 1 )
  2653.         return(0);
  2654.     net_len = (net_len << 8) | c;
  2655.     debug(F111,"krb4_des_read","net_len",net_len);
  2656.     /* Note: net_len is unsigned */
  2657.     if (net_len > sizeof(des_inbuf)) {
  2658.         /* XXX preposterous length, probably out of sync.
  2659.         act as if pipe closed */
  2660.         return(0);
  2661.     }
  2662.     /* the writer tells us how much real data we are getting, but
  2663.     we need to read the pad bytes (8-byte boundary) */
  2664. #ifndef roundup
  2665. #define roundup(x,y) ((((x)+(y)-1)/(y))*(y))
  2666. #endif /* roundup */
  2667.     rd_len = roundup(net_len, 8);
  2668.     debug(F111,"krb4_des_read","rd_len",rd_len);
  2669.     cc = krb_net_read(fd, des_inbuf, rd_len);
  2670.     debug(F111,"krb_net_read","chars read",cc);
  2671.     if (cc < 0) {
  2672.         netclos();
  2673.         return(-1);
  2674.     } else if ( cc != rd_len )
  2675.         return(0);
  2676.     hexdump("krb4_des_read des_inbuf",des_inbuf,8);
  2677. #ifdef CK_ENCRYPTION
  2678. #ifdef NT
  2679.     (void) des_pcbc_encrypt(des_inbuf,
  2680.                              storage,
  2681.                              (net_len < 8) ? 8 : net_len,
  2682.                              k4_sched,
  2683.                              cred.session,
  2684.                              DECRYPT);
  2685. #else /* NT */
  2686.     (void) des_pcbc_encrypt((Block *)des_inbuf,
  2687.                              (Block *)storage,
  2688.                              (net_len < 8) ? 8 : net_len,
  2689.                              k4_sched,
  2690.                              &cred.session,
  2691.                              DECRYPT);
  2692. #endif /* NT */
  2693. #endif /* ENCRYPTION */
  2694.     hexdump("krb4_des_read storage",storage,8);
  2695.     /*
  2696.     * when the cleartext block is < 8 bytes, it is "right-justified"
  2697.     * in the block, so we need to adjust the pointer to the data
  2698.     */
  2699.     if (net_len < 8)
  2700.         store_ptr = storage + 8 - net_len;
  2701.     else
  2702.         store_ptr = storage;
  2703.     nstored = net_len;
  2704.     if ( !buf )
  2705.         return(0);
  2706.     if (nstored > len) {
  2707.         memcpy(buf, store_ptr, len);
  2708.         nreturned += len;
  2709.         store_ptr += len;
  2710.         nstored -= len;
  2711.     } else {
  2712.         memcpy(buf, store_ptr, nstored);
  2713.         nreturned += nstored;
  2714.         nstored = 0;
  2715.     }
  2716.     debug(F111,"krb_net_read","nreturned",nreturned);
  2717.     return(nreturned);
  2718. }
  2719. int
  2720. krb4_des_write(fd, buf, len)
  2721. int fd;
  2722. char *buf;
  2723. int len;
  2724. {
  2725.     static char garbage_buf[8];
  2726.     unsigned char *len_buf = (unsigned char *) des_outpkt;
  2727.     int cc;
  2728.     debug(F111,"krb4_des_write","rlog_encrypt",rlog_encrypt);
  2729.     if ( !rlog_encrypt ) {
  2730.         cc = krb_net_write(fd, buf, len);
  2731.         debug(F111,"krb_net_write","chars written",cc);
  2732.         return(cc);
  2733.     }
  2734.     /*
  2735.     * pcbc_encrypt outputs in 8-byte (64 bit) increments
  2736.     *
  2737.     * it zero-fills the cleartext to 8-byte padding,
  2738.     * so if we have cleartext of < 8 bytes, we want
  2739.     * to insert random garbage before it so that the ciphertext
  2740.     * differs for each transmission of the same cleartext.
  2741.     * if len < 8 - sizeof(long), sizeof(long) bytes of random
  2742.     * garbage should be sufficient; leave the rest as-is in the buffer.
  2743.     * if len > 8 - sizeof(long), just garbage fill the rest.
  2744.     */
  2745.     if (len < 8) {
  2746.         random_confounder(8 - len, garbage_buf);
  2747.         /* this "right-justifies" the data in the buffer */
  2748.         (void) memcpy(garbage_buf + 8 - len, buf, len);
  2749.     }
  2750.     if ( len < 8 )
  2751.         hexdump("krb4_des_write garbage_buf",garbage_buf,8);
  2752.     else
  2753.         hexdump("krb4_des_write buf",buf,8);
  2754. #ifdef CK_ENCRYPTION
  2755. #ifdef NT
  2756.     (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf,
  2757.                              des_outpkt+4,
  2758.                              (len < 8) ? 8 : len,
  2759.                              k4_sched,
  2760.                              cred.session,
  2761.                              ENCRYPT);
  2762. #else /* NT */
  2763.     (void) des_pcbc_encrypt((Block *)((len < 8) ? garbage_buf : buf),
  2764.                              (Block *)(des_outpkt+4),
  2765.                              (len < 8) ? 8 : len,
  2766.                              k4_sched,
  2767.                              &cred.session,
  2768.                              ENCRYPT);
  2769. #endif /* NT */
  2770. #endif /* ENCRYPTION */
  2771.     if ( len < 8 )
  2772.         hexdump("krb4_des_write (post pcbc) garbage_buf",garbage_buf,8);
  2773.     else
  2774.         hexdump("krb4_des_write (post pcbc) buf",buf,8);
  2775.     hexdump("krb4_des_write (des_outpkt+4)",(des_outpkt+4),8);
  2776.     /* tell the other end the real amount, but send an 8-byte padded
  2777.     packet */
  2778.     len_buf[0] = (len & 0xff000000) >> 24;
  2779.     len_buf[1] = (len & 0xff0000) >> 16;
  2780.     len_buf[2] = (len & 0xff00) >> 8;
  2781.     len_buf[3] = (len & 0xff);
  2782.     hexdump("krb4_des_write des_outpkt len",des_outpkt,12);
  2783.     cc = krb_net_write(fd, des_outpkt, roundup(len,8)+4);
  2784.     debug(F111,"krb_net_write","chars written",cc);
  2785.     return(len);
  2786. }
  2787. #endif /* KRB4 */
  2788. #ifdef KRB524
  2789. /* The following functions are missing from the compatibility library */
  2790. const char *
  2791. krb_get_err_text_entry(r) int r;
  2792. {
  2793.     extern char krb_err_text[];
  2794.     return(krb_err_txt[r]);
  2795. }
  2796. #endif /* KRB524 */
  2797. #endif /* CK_KERBEROS */
  2798. #endif /* RLOGCODE */
  2799. #endif /* CK_AUTHENTICATION */