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 $ */
22 /* $DragonFly: src/crypto/kerberosIV/lib/krb/Attic/recvauth.c,v 1.2 2003/06/17 04:24:36 dillon Exp $ */
26 RCSID("$Id: recvauth.c,v 1.19 1998/06/09 19:25:25 joda Exp $");
29 * krb_recvauth() reads (and optionally responds to) a message sent
30 * using krb_sendauth(). The "options" argument is a bit-field of
31 * selected options (see "sendauth.c" for options description).
32 * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
33 * (mutual authentication requested). The "fd" argument supplies
34 * a file descriptor to read from (and write to, if mutual authenti-
35 * cation is requested).
37 * Part of the received message will be a Kerberos ticket sent by the
38 * client; this is read into the "ticket" argument. The "service" and
39 * "instance" arguments supply the server's Kerberos name. If the
40 * "instance" argument is the string "*", it is treated as a wild card
41 * and filled in during the krb_rd_req() call (see read_service_key()).
43 * The "faddr" and "laddr" give the sending (client) and receiving
44 * (local server) network addresses. ("laddr" may be left NULL unless
45 * mutual authentication is requested, in which case it must be set.)
47 * The authentication information extracted from the message is returned
48 * in "kdata". The "filename" argument indicates the file where the
49 * server's key can be found. (It is passed on to krb_rd_req().) If
50 * left null, the default "/etc/srvtab" will be used.
52 * If mutual authentication is requested, the session key schedule must
53 * be computed in order to reply; this schedule is returned in the
54 * "schedule" argument. A string containing the application version
55 * number from the received message is returned in "version", which
56 * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
58 * See krb_sendauth() for the format of the received client message.
60 * krb_recvauth() first reads the protocol version string from the
61 * given file descriptor. If it doesn't match the current protocol
62 * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In
63 * that case, the string of characters up to the first space is read
64 * and interpreted as the ticket length, then the ticket is read.
66 * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
67 * next reads the application protocol version string. Then the
68 * ticket length and ticket itself are read.
70 * The ticket is decrypted and checked by the call to krb_rd_req().
71 * If no mutual authentication is required, the result of the
72 * krb_rd_req() call is retured by this routine. If mutual authenti-
73 * cation is required, a message in the following format is returned
79 * 4 bytes tkt_len length of ticket or -1
82 * priv_len tmp_buf "private" message created
83 * by krb_mk_priv() which
84 * contains the incremented
85 * checksum sent by the client
86 * encrypted in the session
87 * key. (This field is not
88 * present in case of error.)
90 * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
91 * other error code is returned.
95 send_error_reply(int fd)
97 unsigned char tmp[4] = { 255, 255, 255, 255 };
98 if(krb_net_write(fd, tmp, sizeof(tmp)) != sizeof(tmp))
104 krb_recvauth(int32_t options, /* bit-pattern of options */
105 int fd, /* file descr. to read from */
106 KTEXT ticket, /* storage for client's ticket */
107 char *service, /* service expected */
108 char *instance, /* inst expected (may be filled in) */
109 struct sockaddr_in *faddr, /* address of foreign host on fd */
110 struct sockaddr_in *laddr, /* local address */
111 AUTH_DAT *kdata, /* kerberos data (returned) */
112 char *filename, /* name of file with service keys */
113 des_key_schedule schedule, /* key schedule (return) */
114 char *version) /* version string (filled in) */
117 char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
120 u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
122 if (!(options & KOPT_IGNORE_PROTOCOL)) {
123 /* read the protocol version number */
124 if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) != KRB_SENDAUTH_VLEN)
126 krb_vers[KRB_SENDAUTH_VLEN] = '\0';
129 /* read the application version string */
130 if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) != KRB_SENDAUTH_VLEN)
132 version[KRB_SENDAUTH_VLEN] = '\0';
134 /* get the length of the ticket */
137 if (krb_net_read(fd, tmp, 4) != 4)
139 krb_get_int(tmp, &ticket->length, 4, 0);
143 if (ticket->length <= 0 || ticket->length > MAX_KTXT_LEN) {
144 if (options & KOPT_DO_MUTUAL) {
145 if(send_error_reply(fd))
149 return KFAILURE; /* XXX there may still be junk on the fd? */
152 /* read the ticket */
153 if (krb_net_read(fd, ticket->dat, ticket->length) != ticket->length)
156 * now have the ticket. decrypt it to get the authenticated
159 rem = krb_rd_req(ticket, service, instance, faddr->sin_addr.s_addr,
162 /* if we are doing mutual auth, compose a response */
163 if (options & KOPT_DO_MUTUAL) {
164 if (rem != KSUCCESS){
165 /* the krb_rd_req failed */
166 if(send_error_reply(fd))
171 /* add one to the (formerly) sealed checksum, and re-seal it
172 for return to the client */
175 krb_put_int(kdata->checksum + 1, cs, sizeof(cs), 4);
177 des_key_sched(&kdata->session,schedule);
179 priv_len = krb_mk_priv(cs,
187 /* mk_priv will never fail */
188 priv_len += krb_put_int(priv_len, tmp_buf, 4, 4);
190 if((cc = krb_net_write(fd, tmp_buf, priv_len)) != priv_len)