Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / crypto / kerberosIV / lib / krb / recvauth.c
1 /* 
2   Copyright (C) 1989 by the Massachusetts Institute of Technology
3
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.
8
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
18 or implied warranty.
19
20   */
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 $ */
23
24 #include "krb_locl.h"
25
26 RCSID("$Id: recvauth.c,v 1.19 1998/06/09 19:25:25 joda Exp $");
27
28 /*
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).
36  *
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()).
42  *
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.)
46  *
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.
51  *
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.
57  *
58  * See krb_sendauth() for the format of the received client message.
59  *
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.
65  *
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.
69  *
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
74  * on "fd":
75  *
76  * Size                 Variable                Field
77  * ----                 --------                -----
78  *
79  * 4 bytes              tkt_len                 length of ticket or -1
80  *                                              if error occurred
81  *
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.)
89  *
90  * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some
91  * other error code is returned.
92  */
93
94 static int
95 send_error_reply(int fd)
96 {
97     unsigned char tmp[4] = { 255, 255, 255, 255 };
98     if(krb_net_write(fd, tmp, sizeof(tmp)) != sizeof(tmp))
99         return -1;
100     return 0;
101 }
102
103 int
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) */
115 {
116     int cc;
117     char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */
118     int rem;
119     int32_t priv_len;
120     u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)];
121
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)
125             return(errno);
126         krb_vers[KRB_SENDAUTH_VLEN] = '\0';
127     }
128
129     /* read the application version string */
130     if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) != KRB_SENDAUTH_VLEN)
131         return(errno);
132     version[KRB_SENDAUTH_VLEN] = '\0';
133
134     /* get the length of the ticket */
135     {
136         char tmp[4];
137         if (krb_net_read(fd, tmp, 4) != 4)
138             return -1;
139         krb_get_int(tmp, &ticket->length, 4, 0);
140     }
141     
142     /* sanity check */
143     if (ticket->length <= 0 || ticket->length > MAX_KTXT_LEN) {
144         if (options & KOPT_DO_MUTUAL) {
145             if(send_error_reply(fd))
146                 return -1;
147             return KFAILURE;
148         } else
149             return KFAILURE; /* XXX there may still be junk on the fd? */
150     }
151
152     /* read the ticket */
153     if (krb_net_read(fd, ticket->dat, ticket->length) != ticket->length)
154         return -1;
155     /*
156      * now have the ticket.  decrypt it to get the authenticated
157      * data.
158      */
159     rem = krb_rd_req(ticket, service, instance, faddr->sin_addr.s_addr,
160                      kdata, filename);
161
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))
167                 return -1;
168             return rem;
169         }
170         
171         /* add one to the (formerly) sealed checksum, and re-seal it
172            for return to the client */
173         { 
174             unsigned char cs[4];
175             krb_put_int(kdata->checksum + 1, cs, sizeof(cs), 4);
176 #ifndef NOENCRYPTION
177             des_key_sched(&kdata->session,schedule);
178 #endif
179             priv_len = krb_mk_priv(cs, 
180                                    tmp_buf+4, 
181                                    4,
182                                    schedule,
183                                    &kdata->session,
184                                    laddr,
185                                    faddr);
186         }
187         /* mk_priv will never fail */
188         priv_len += krb_put_int(priv_len, tmp_buf, 4, 4);
189         
190         if((cc = krb_net_write(fd, tmp_buf, priv_len)) != priv_len)
191             return -1;
192     }
193     return rem;
194 }