2 Copyright (C) 1989 by the Massachusetts Institute of Technology
4 Export of this software from the United States of America is assumed
5 to require a specific license from the United States Government.
6 It is the responsibility of any person or organization contemplating
7 export to obtain such a license before exporting.
9 WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10 distribute this software and its documentation for any purpose and
11 without fee is hereby granted, provided that the above copyright
12 notice appear in all copies and that both that copyright notice and
13 this permission notice appear in supporting documentation, and that
14 the name of M.I.T. not be used in advertising or publicity pertaining
15 to distribution of the software without specific, written prior
16 permission. M.I.T. makes no representations about the suitability of
17 this software for any purpose. It is provided "as is" without express
21 /* $FreeBSD: src/crypto/kerberosIV/lib/krb/recvauth.c,v 1.1.1.2.2.1 2003/02/13 21:34:36 nectar Exp $ */
25 RCSID("$Id: recvauth.c,v 1.19 1998/06/09 19:25:25 joda Exp $");
28 * krb_recvauth() reads (and optionally responds to) a message sent
29 * using krb_sendauth(). The "options" argument is a bit-field of
30 * selected options (see "sendauth.c" for options description).
31 * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
32 * (mutual authentication requested). The "fd" argument supplies
33 * a file descriptor to read from (and write to, if mutual authenti-
34 * cation is requested).
36 * Part of the received message will be a Kerberos ticket sent by the
37 * client; this is read into the "ticket" argument. The "service" and
38 * "instance" arguments supply the server's Kerberos name. If the
39 * "instance" argument is the string "*", it is treated as a wild card
40 * and filled in during the krb_rd_req() call (see read_service_key()).
42 * The "faddr" and "laddr" give the sending (client) and receiving
43 * (local server) network addresses. ("laddr" may be left NULL unless
44 * mutual authentication is requested, in which case it must be set.)
46 * The authentication information extracted from the message is returned
47 * in "kdata". The "filename" argument indicates the file where the
48 * server's key can be found. (It is passed on to krb_rd_req().) If
49 * left null, the default "/etc/srvtab" will be used.
51 * If mutual authentication is requested, the session key schedule must
52 * be computed in order to reply; this schedule is returned in the
53 * "schedule" argument. A string containing the application version
54 * number from the received message is returned in "version", which
55 * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
57 * See krb_sendauth() for the format of the received client message.
59 * krb_recvauth() first reads the protocol version string from the
60 * given file descriptor. If it doesn't match the current protocol
61 * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In
62 * that case, the string of characters up to the first space is read
63 * and interpreted as the ticket length, then the ticket is read.
65 * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
66 * next reads the application protocol version string. Then the
67 * ticket length and ticket itself are read.
69 * The ticket is decrypted and checked by the call to krb_rd_req().
70 * If no mutual authentication is required, the result of the
71 * krb_rd_req() call is retured by this routine. If mutual authenti-
72 * cation is required, a message in the following format is returned
78 * 4 bytes tkt_len length of ticket or -1
81 * priv_len tmp_buf "private" message created
82 * by krb_mk_priv() which
83 * contains the incremented
84 * checksum sent by the client
85 * encrypted in the session
86 * key. (This field is not
87 * present in case of error.)
89 * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
90 * other error code is returned.
94 send_error_reply(int fd)
96 unsigned char tmp[4] = { 255, 255, 255, 255 };
97 if(krb_net_write(fd, tmp, sizeof(tmp)) != sizeof(tmp))
103 krb_recvauth(int32_t options, /* bit-pattern of options */
104 int fd, /* file descr. to read from */
105 KTEXT ticket, /* storage for client's ticket */
106 char *service, /* service expected */
107 char *instance, /* inst expected (may be filled in) */
108 struct sockaddr_in *faddr, /* address of foreign host on fd */
109 struct sockaddr_in *laddr, /* local address */
110 AUTH_DAT *kdata, /* kerberos data (returned) */
111 char *filename, /* name of file with service keys */
112 des_key_schedule schedule, /* key schedule (return) */
113 char *version) /* version string (filled in) */
116 char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
119 u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
121 if (!(options & KOPT_IGNORE_PROTOCOL)) {
122 /* read the protocol version number */
123 if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) != KRB_SENDAUTH_VLEN)
125 krb_vers[KRB_SENDAUTH_VLEN] = '\0';
128 /* read the application version string */
129 if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) != KRB_SENDAUTH_VLEN)
131 version[KRB_SENDAUTH_VLEN] = '\0';
133 /* get the length of the ticket */
136 if (krb_net_read(fd, tmp, 4) != 4)
138 krb_get_int(tmp, &ticket->length, 4, 0);
142 if (ticket->length <= 0 || ticket->length > MAX_KTXT_LEN) {
143 if (options & KOPT_DO_MUTUAL) {
144 if(send_error_reply(fd))
148 return KFAILURE; /* XXX there may still be junk on the fd? */
151 /* read the ticket */
152 if (krb_net_read(fd, ticket->dat, ticket->length) != ticket->length)
155 * now have the ticket. decrypt it to get the authenticated
158 rem = krb_rd_req(ticket, service, instance, faddr->sin_addr.s_addr,
161 /* if we are doing mutual auth, compose a response */
162 if (options & KOPT_DO_MUTUAL) {
163 if (rem != KSUCCESS){
164 /* the krb_rd_req failed */
165 if(send_error_reply(fd))
170 /* add one to the (formerly) sealed checksum, and re-seal it
171 for return to the client */
174 krb_put_int(kdata->checksum + 1, cs, sizeof(cs), 4);
176 des_key_sched(&kdata->session,schedule);
178 priv_len = krb_mk_priv(cs,
186 /* mk_priv will never fail */
187 priv_len += krb_put_int(priv_len, tmp_buf, 4, 4);
189 if((cc = krb_net_write(fd, tmp_buf, priv_len)) != priv_len)