|
|
1.1 root 1: /*
2: * $Source: /usr/src/kerberosIV/krb/RCS/sendauth.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:
12: #ifndef lint
13: static char rcsid_sendauth_c[] =
14: "$Header: /usr/src/kerberosIV/krb/RCS/sendauth.c,v 4.5 90/06/25 20:57:24 kfall Exp $";
15: #endif lint
16:
17: #include <mit-copyright.h>
18:
19: #include <des.h>
20: #include <krb.h>
21: #include <sys/types.h>
22: #include <netinet/in.h>
23: #include <syslog.h>
24: #include <errno.h>
25: #include <stdio.h>
26: #include <strings.h>
27:
28: #define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */
29: /*
30: * If the protocol changes, you will need to change the version string
31: * and make appropriate changes in krb_recvauth.c
32: */
33:
34: extern int errno;
35:
36: extern char *krb_get_phost();
37:
38: /*
39: * This file contains two routines: krb_sendauth() and krb_sendsrv().
40: *
41: * krb_sendauth() transmits a ticket over a file descriptor for a
42: * desired service, instance, and realm, doing mutual authentication
43: * with the server if desired.
44: *
45: * krb_sendsvc() sends a service name to a remote knetd server.
46: */
47:
48: /*
49: * The first argument to krb_sendauth() contains a bitfield of
50: * options (the options are defined in "krb.h"):
51: *
52: * KOPT_DONT_CANON Don't canonicalize instance as a hostname.
53: * (If this option is not chosen, krb_get_phost()
54: * is called to canonicalize it.)
55: *
56: * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos.
57: * A ticket must be supplied in the "ticket"
58: * argument.
59: * (If this option is not chosen, and there
60: * is no ticket for the given server in the
61: * ticket cache, one will be fetched using
62: * krb_mk_req() and returned in "ticket".)
63: *
64: * KOPT_DO_MUTUAL Do mutual authentication, requiring that the
65: * receiving server return the checksum+1 encrypted
66: * in the session key. The mutual authentication
67: * is done using krb_mk_priv() on the other side
68: * (see "recvauth.c") and krb_rd_priv() on this
69: * side.
70: *
71: * The "fd" argument is a file descriptor to write to the remote
72: * server on. The "ticket" argument is used to store the new ticket
73: * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
74: * chosen, the ticket must be supplied in the "ticket" argument.
75: * The "service", "inst", and "realm" arguments identify the ticket.
76: * If "realm" is null, the local realm is used.
77: *
78: * The following arguments are only needed if the KOPT_DO_MUTUAL option
79: * is chosen:
80: *
81: * The "checksum" argument is a number that the server will add 1 to
82: * to authenticate itself back to the client; the "msg_data" argument
83: * holds the returned mutual-authentication message from the server
84: * (i.e., the checksum+1); the "cred" structure is used to hold the
85: * session key of the server, extracted from the ticket file, for use
86: * in decrypting the mutual authentication message from the server;
87: * and "schedule" holds the key schedule for that decryption. The
88: * the local and server addresses are given in "laddr" and "faddr".
89: *
90: * The application protocol version number (of up to KRB_SENDAUTH_VLEN
91: * characters) is passed in "version".
92: *
93: * If all goes well, KSUCCESS is returned, otherwise some error code.
94: *
95: * The format of the message sent to the server is:
96: *
97: * Size Variable Field
98: * ---- -------- -----
99: *
100: * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol
101: * bytes version number
102: *
103: * KRB_SENDAUTH_VLEN version application protocol
104: * bytes version number
105: *
106: * 4 bytes ticket->length length of ticket
107: *
108: * ticket->length ticket->dat ticket itself
109: */
110:
111: /*
112: * XXX: Note that krb_rd_priv() is coded in such a way that
113: * "msg_data->app_data" will be pointing into "priv_buf", which
114: * will disappear when krb_sendauth() returns.
115: */
116:
117: int
118: krb_sendauth(options, fd, ticket, service, inst, realm, checksum,
119: msg_data, cred, schedule, laddr, faddr, version)
120: long options; /* bit-pattern of options */
121: int fd; /* file descriptor to write onto */
122: KTEXT ticket; /* where to put ticket (return); or
123: * supplied in case of KOPT_DONT_MK_REQ */
124: char *service, *inst, *realm; /* service name, instance, realm */
125: u_long checksum; /* checksum to include in request */
126: MSG_DAT *msg_data; /* mutual auth MSG_DAT (return) */
127: CREDENTIALS *cred; /* credentials (return) */
128: Key_schedule schedule; /* key schedule (return) */
129: struct sockaddr_in *laddr; /* local address */
130: struct sockaddr_in *faddr; /* address of foreign host on fd */
131: char *version; /* version string */
132: {
133: int rem, i, cc;
134: char srv_inst[INST_SZ];
135: char krb_realm[REALM_SZ];
136: char buf[BUFSIZ];
137: long tkt_len;
138: u_char priv_buf[1024];
139: u_long cksum;
140:
141: rem=KSUCCESS;
142:
143: /* get current realm if not passed in */
144: if (!realm) {
145: rem = krb_get_lrealm(krb_realm,1);
146: if (rem != KSUCCESS)
147: return(rem);
148: realm = krb_realm;
149: }
150:
151: /* copy instance into local storage, canonicalizing if desired */
152: if (options & KOPT_DONT_CANON)
153: (void) strncpy(srv_inst, inst, INST_SZ);
154: else
155: (void) strncpy(srv_inst, krb_get_phost(inst), INST_SZ);
156:
157: /* get the ticket if desired */
158: if (!(options & KOPT_DONT_MK_REQ)) {
159: rem = krb_mk_req(ticket, service, srv_inst, realm, checksum);
160: if (rem != KSUCCESS)
161: return(rem);
162: }
163:
164: #ifdef ATHENA_COMPAT
165: /* this is only for compatibility with old servers */
166: if (options & KOPT_DO_OLDSTYLE) {
167: (void) sprintf(buf,"%d ",ticket->length);
168: (void) write(fd, buf, strlen(buf));
169: (void) write(fd, (char *) ticket->dat, ticket->length);
170: return(rem);
171: }
172: #endif ATHENA_COMPAT
173: /* if mutual auth, get credentials so we have service session
174: keys for decryption below */
175: if (options & KOPT_DO_MUTUAL)
176: if (cc = krb_get_cred(service, srv_inst, realm, cred))
177: return(cc);
178:
179: /* zero the buffer */
180: (void) bzero(buf, BUFSIZ);
181:
182: /* insert version strings */
183: (void) strncpy(buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN);
184: (void) strncpy(buf+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN);
185:
186: /* increment past vers strings */
187: i = 2*KRB_SENDAUTH_VLEN;
188:
189: /* put ticket length into buffer */
190: tkt_len = htonl((unsigned long) ticket->length);
191: (void) bcopy((char *) &tkt_len, buf+i, sizeof(tkt_len));
192: i += sizeof(tkt_len);
193:
194: /* put ticket into buffer */
195: (void) bcopy((char *) ticket->dat, buf+i, ticket->length);
196: i += ticket->length;
197:
198: /* write the request to the server */
199: if ((cc = krb_net_write(fd, buf, i)) != i)
200: return(cc);
201:
202: /* mutual authentication, if desired */
203: if (options & KOPT_DO_MUTUAL) {
204: /* get the length of the reply */
205: if (krb_net_read(fd, (char *) &tkt_len, sizeof(tkt_len)) !=
206: sizeof(tkt_len))
207: return(errno);
208: tkt_len = ntohl((unsigned long)tkt_len);
209:
210: /* if the length is negative, the server failed to recognize us. */
211: if (tkt_len < 0)
212: return(KFAILURE); /* XXX */
213: /* read the reply... */
214: if (krb_net_read(fd, (char *)priv_buf, (int) tkt_len) != (int) tkt_len)
215: return(errno);
216:
217: /* ...and decrypt it */
218: #ifndef NOENCRYPTION
219: key_sched(cred->session, schedule);
220: #endif /* !NOENCRYPTION */
221: if (cc = krb_rd_priv(priv_buf,(unsigned long) tkt_len, schedule,
222: cred->session, faddr, laddr, msg_data))
223: return(cc);
224:
225: /* fetch the (modified) checksum */
226: (void) bcopy((char *)msg_data->app_data, (char *)&cksum,
227: sizeof(cksum));
228: cksum = ntohl(cksum);
229:
230: /* if it doesn't match, fail */
231: if (cksum != checksum + 1)
232: return(KFAILURE); /* XXX */
233: }
234: return(KSUCCESS);
235: }
236:
237: #ifdef ATHENA_COMPAT
238: /*
239: * krb_sendsvc
240: */
241:
242: int
243: krb_sendsvc(fd, service)
244: int fd;
245: char *service;
246: {
247: /* write the service name length and then the service name to
248: the fd */
249: long serv_length;
250: int cc;
251:
252: serv_length = htonl((unsigned long)strlen(service));
253: if ((cc = krb_net_write(fd, (char *) &serv_length,
254: sizeof(serv_length)))
255: != sizeof(serv_length))
256: return(cc);
257: if ((cc = krb_net_write(fd, service, strlen(service)))
258: != strlen(service))
259: return(cc);
260: return(KSUCCESS);
261: }
262: #endif ATHENA_COMPAT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.