|
|
1.1 root 1: /*
2: * $Source: /usr/src/kerberosIV/src/lib/krb/RCS/recvauth.c,v $
3: * $Author: kfall $
4: *
5: * Copyright 1987, 1988 by the Massachusetts Institute of Technology.
6: *
7: * For copying and distribution information, please see the file
8: * <mit-copyright.h>.
9: */
10:
11: #ifndef lint
12: static char rcsid_recvauth_c[] =
13: "$Header: /usr/src/kerberosIV/src/lib/krb/RCS/recvauth.c,v 4.4 90/05/12 00:58:56 kfall Exp $";
14: #endif lint
15:
16: #include <mit-copyright.h>
17:
18: #include <des.h>
19: #include <krb.h>
20: #include <sys/types.h>
21: #include <netinet/in.h>
22: #include <syslog.h>
23: #include <errno.h>
24: #include <stdio.h>
25: #include <strings.h>
26:
27:
28: #define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN
29: chars */
30:
31: /*
32: * If the protocol changes, you will need to change the version string
33: * and make appropriate changes in krb_sendauth.c
34: * be sure to support old versions of krb_sendauth!
35: */
36:
37: extern int errno;
38:
39: /*
40: * krb_recvauth() reads (and optionally responds to) a message sent
41: * using krb_sendauth(). The "options" argument is a bit-field of
42: * selected options (see "sendauth.c" for options description).
43: * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL
44: * (mutual authentication requested). The "fd" argument supplies
45: * a file descriptor to read from (and write to, if mutual authenti-
46: * cation is requested).
47: *
48: * Part of the received message will be a Kerberos ticket sent by the
49: * client; this is read into the "ticket" argument. The "service" and
50: * "instance" arguments supply the server's Kerberos name. If the
51: * "instance" argument is the string "*", it is treated as a wild card
52: * and filled in during the krb_rd_req() call (see read_service_key()).
53: *
54: * The "faddr" and "laddr" give the sending (client) and receiving
55: * (local server) network addresses. ("laddr" may be left NULL unless
56: * mutual authentication is requested, in which case it must be set.)
57: *
58: * The authentication information extracted from the message is returned
59: * in "kdata". The "filename" argument indicates the file where the
60: * server's key can be found. (It is passed on to krb_rd_req().) If
61: * left null, the default "/etc/srvtab" will be used.
62: *
63: * If mutual authentication is requested, the session key schedule must
64: * be computed in order to reply; this schedule is returned in the
65: * "schedule" argument. A string containing the application version
66: * number from the received message is returned in "version", which
67: * should be large enough to hold a KRB_SENDAUTH_VLEN-character string.
68: *
69: * See krb_sendauth() for the format of the received client message.
70: *
71: * This routine supports another client format, for backward
72: * compatibility, consisting of:
73: *
74: * Size Variable Field
75: * ---- -------- -----
76: *
77: * string tmp_buf, tkt_len length of ticket, in
78: * ascii
79: *
80: * char ' ' (space char) separator
81: *
82: * tkt_len ticket->dat the ticket
83: *
84: * This old-style version does not support mutual authentication.
85: *
86: * krb_recvauth() first reads the protocol version string from the
87: * given file descriptor. If it doesn't match the current protocol
88: * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In
89: * that case, the string of characters up to the first space is read
90: * and interpreted as the ticket length, then the ticket is read.
91: *
92: * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth()
93: * next reads the application protocol version string. Then the
94: * ticket length and ticket itself are read.
95: *
96: * The ticket is decrypted and checked by the call to krb_rd_req().
97: * If no mutual authentication is required, the result of the
98: * krb_rd_req() call is retured by this routine. If mutual authenti-
99: * cation is required, a message in the following format is returned
100: * on "fd":
101: *
102: * Size Variable Field
103: * ---- -------- -----
104: *
105: * 4 bytes tkt_len length of ticket or -1
106: * if error occurred
107: *
108: * priv_len tmp_buf "private" message created
109: * by krb_mk_priv() which
110: * contains the incremented
111: * checksum sent by the client
112: * encrypted in the session
113: * key. (This field is not
114: * present in case of error.)
115: *
116: * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
117: * other error code is returned.
118: */
119:
120: int
121: krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata,
122: filename, schedule, version)
123: long options; /* bit-pattern of options */
124: int fd; /* file descr. to read from */
125: KTEXT ticket; /* storage for client's ticket */
126: char *service; /* service expected */
127: char *instance; /* inst expected (may be filled in) */
128: struct sockaddr_in *faddr; /* address of foreign host on fd */
129: struct sockaddr_in *laddr; /* local address */
130: AUTH_DAT *kdata; /* kerberos data (returned) */
131: char *filename; /* name of file with service keys */
132: Key_schedule schedule; /* key schedule (return) */
133: char *version; /* version string (filled in) */
134: {
135:
136: int i, cc, old_vers = 0;
137: char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
138: char *cp;
139: int rem;
140: long tkt_len, priv_len;
141: u_long cksum;
142: u_char tmp_buf[1024];
143:
144: /* read the protocol version number */
145: if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) !=
146: KRB_SENDAUTH_VLEN)
147: return(errno);
148: krb_vers[KRB_SENDAUTH_VLEN] = '\0';
149:
150: /* check version string */
151: if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) {
152: /* Assume the old version of sendkerberosdata: send ascii
153: length, ' ', and ticket. */
154: if (options & KOPT_DO_MUTUAL)
155: return(KFAILURE); /* XXX can't do old style with mutual auth */
156: old_vers = 1;
157:
158: /* copy what we have read into tmp_buf */
159: (void) bcopy(krb_vers, (char *) tmp_buf, KRB_SENDAUTH_VLEN);
160:
161: /* search for space, and make it a null */
162: for (i = 0; i < KRB_SENDAUTH_VLEN; i++)
163: if (tmp_buf[i]== ' ') {
164: tmp_buf[i] = '\0';
165: /* point cp to the beginning of the real ticket */
166: cp = (char *) &tmp_buf[i+1];
167: break;
168: }
169:
170: if (i == KRB_SENDAUTH_VLEN)
171: /* didn't find the space, keep reading to find it */
172: for (; i<20; i++) {
173: if (read(fd, (char *)&tmp_buf[i], 1) != 1) {
174: return(KFAILURE);
175: }
176: if (tmp_buf[i] == ' ') {
177: tmp_buf[i] = '\0';
178: /* point cp to the beginning of the real ticket */
179: cp = (char *) &tmp_buf[i+1];
180: break;
181: }
182: }
183:
184: tkt_len = (long) atoi((char *) tmp_buf);
185:
186: /* sanity check the length */
187: if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN))
188: return(KFAILURE);
189:
190: if (i < KRB_SENDAUTH_VLEN) {
191: /* since we already got the space, and part of the ticket,
192: we read fewer bytes to get the rest of the ticket */
193: if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN),
194: (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
195: != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i))
196: return(errno);
197: } else {
198: if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) !=
199: (int) tkt_len)
200: return(errno);
201: }
202: ticket->length = tkt_len;
203: /* copy the ticket into the struct */
204: (void) bcopy(cp, (char *) ticket->dat, ticket->length);
205:
206: } else {
207: /* read the application version string */
208: if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) !=
209: KRB_SENDAUTH_VLEN)
210: return(errno);
211: version[KRB_SENDAUTH_VLEN] = '\0';
212:
213: /* get the length of the ticket */
214: if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) !=
215: sizeof(tkt_len))
216: return(errno);
217:
218: /* sanity check */
219: ticket->length = ntohl((unsigned long)tkt_len);
220: if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) {
221: if (options & KOPT_DO_MUTUAL) {
222: rem = KFAILURE;
223: goto mutual_fail;
224: } else
225: return(KFAILURE); /* XXX there may still be junk on the fd? */
226: }
227:
228: /* read the ticket */
229: if (krb_net_read(fd, (char *) ticket->dat, ticket->length)
230: != ticket->length)
231: return(errno);
232: }
233: /*
234: * now have the ticket. decrypt it to get the authenticated
235: * data.
236: */
237: rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr,
238: kdata,filename);
239:
240: if (old_vers) return(rem); /* XXX can't do mutual with old client */
241:
242: /* if we are doing mutual auth, compose a response */
243: if (options & KOPT_DO_MUTUAL) {
244: if (rem != KSUCCESS)
245: /* the krb_rd_req failed */
246: goto mutual_fail;
247:
248: /* add one to the (formerly) sealed checksum, and re-seal it
249: for return to the client */
250: cksum = kdata->checksum + 1;
251: cksum = htonl(cksum);
252: #ifndef NOENCRYPTION
253: key_sched(kdata->session,schedule);
254: #endif /* !NOENCRYPTION */
255: priv_len = krb_mk_priv((unsigned char *)&cksum,
256: tmp_buf,
257: (unsigned long) sizeof(cksum),
258: schedule,
259: kdata->session,
260: laddr,
261: faddr);
262: if (priv_len < 0) {
263: /* re-sealing failed; notify the client */
264: rem = KFAILURE; /* XXX */
265: mutual_fail:
266: priv_len = -1;
267: tkt_len = htonl((unsigned long) priv_len);
268: /* a length of -1 is interpreted as an authentication
269: failure by the client */
270: if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
271: != sizeof(tkt_len))
272: return(cc);
273: return(rem);
274: } else {
275: /* re-sealing succeeded, send the private message */
276: tkt_len = htonl((unsigned long)priv_len);
277: if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len)))
278: != sizeof(tkt_len))
279: return(cc);
280: if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len))
281: != (int) priv_len)
282: return(cc);
283: }
284: }
285: return(rem);
286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.