Initial import from FreeBSD RELENG_4:
[dragonfly.git] / crypto / kerberosIV / lib / krb / sendauth.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/sendauth.c,v 1.1.1.3.2.1 2003/02/13 21:34:36 nectar Exp $ */
22
23 #include "krb_locl.h"
24
25 RCSID("$Id: sendauth.c,v 1.18 1999/09/16 20:41:55 assar Exp $");
26
27 /*
28  * krb_sendauth() transmits a ticket over a file descriptor for a
29  * desired service, instance, and realm, doing mutual authentication
30  * with the server if desired.
31  */
32
33 /*
34  * The first argument to krb_sendauth() contains a bitfield of
35  * options (the options are defined in "krb.h"):
36  *
37  * KOPT_DONT_CANON      Don't canonicalize instance as a hostname.
38  *                      (If this option is not chosen, krb_get_phost()
39  *                      is called to canonicalize it.)
40  *
41  * KOPT_DONT_MK_REQ     Don't request server ticket from Kerberos.
42  *                      A ticket must be supplied in the "ticket"
43  *                      argument.
44  *                      (If this option is not chosen, and there
45  *                      is no ticket for the given server in the
46  *                      ticket cache, one will be fetched using
47  *                      krb_mk_req() and returned in "ticket".)
48  *
49  * KOPT_DO_MUTUAL       Do mutual authentication, requiring that the
50  *                      receiving server return the checksum+1 encrypted
51  *                      in the session key.  The mutual authentication
52  *                      is done using krb_mk_priv() on the other side
53  *                      (see "recvauth.c") and krb_rd_priv() on this
54  *                      side.
55  *
56  * The "fd" argument is a file descriptor to write to the remote
57  * server on.  The "ticket" argument is used to store the new ticket
58  * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is
59  * chosen, the ticket must be supplied in the "ticket" argument.
60  * The "service", "inst", and "realm" arguments identify the ticket.
61  * If "realm" is null, the local realm is used.
62  *
63  * The following arguments are only needed if the KOPT_DO_MUTUAL option
64  * is chosen:
65  *
66  *   The "checksum" argument is a number that the server will add 1 to
67  *   to authenticate itself back to the client; the "msg_data" argument
68  *   holds the returned mutual-authentication message from the server
69  *   (i.e., the checksum+1); the "cred" structure is used to hold the
70  *   session key of the server, extracted from the ticket file, for use
71  *   in decrypting the mutual authentication message from the server;
72  *   and "schedule" holds the key schedule for that decryption.  The
73  *   the local and server addresses are given in "laddr" and "faddr".
74  *
75  * The application protocol version number (of up to KRB_SENDAUTH_VLEN
76  * characters) is passed in "version".
77  *
78  * If all goes well, KSUCCESS is returned, otherwise some error code.
79  *
80  * The format of the message sent to the server is:
81  *
82  * Size                 Variable                Field
83  * ----                 --------                -----
84  *
85  * KRB_SENDAUTH_VLEN    KRB_SENDAUTH_VER        sendauth protocol
86  * bytes                                        version number
87  *
88  * KRB_SENDAUTH_VLEN    version                 application protocol
89  * bytes                                        version number
90  *
91  * 4 bytes              ticket->length          length of ticket
92  *
93  * ticket->length       ticket->dat             ticket itself
94  */
95
96 int
97 krb_sendauth(int32_t options,   /* bit-pattern of options */
98              int fd,            /* file descriptor to write onto */
99              KTEXT ticket,      /* where to put ticket (return); or
100                                  * supplied in case of KOPT_DONT_MK_REQ */
101              char *service,     /* service name, instance, realm */
102              char *instance,
103              char *realm,
104              u_int32_t checksum, /* checksum to include in request */
105              MSG_DAT *msg_data, /* mutual auth MSG_DAT (return) */
106              CREDENTIALS *cred, /* credentials (return) */
107              des_key_schedule schedule, /* key schedule (return) */
108              struct sockaddr_in *laddr, /* local address */
109              struct sockaddr_in *faddr, /* address of foreign host on fd */
110              char *version)     /* version string */
111 {
112     int ret;
113     KTEXT_ST buf;
114     char realrealm[REALM_SZ];
115
116     if (realm == NULL) {
117         ret = krb_get_lrealm (realrealm, 1);
118         if (ret != KSUCCESS)
119             return ret;
120         realm = realrealm;
121     }
122     ret = krb_mk_auth (options, ticket, service, instance, realm, checksum,
123                        version, &buf);
124     if (ret != KSUCCESS)
125         return ret;
126     ret = krb_net_write(fd, buf.dat, buf.length);
127     if(ret < 0)
128         return -1;
129       
130     if (options & KOPT_DO_MUTUAL) {
131         char tmp[4];
132         u_int32_t len;
133         char inst[INST_SZ];
134         char *i;
135
136         ret = krb_net_read (fd, tmp, 4);
137         if (ret < 0)
138             return -1;
139
140         krb_get_int (tmp, &len, 4, 0);
141         if (len == 0xFFFFFFFF || len > sizeof(buf.dat))
142             return KFAILURE;
143         buf.length = len;
144         ret = krb_net_read (fd, buf.dat, len);
145         if (ret < 0)
146             return -1;
147
148         if (options & KOPT_DONT_CANON)
149             i = instance;
150         else
151             i = krb_get_phost(instance);
152         strlcpy (inst, i, sizeof(inst));
153
154         ret = krb_get_cred (service, inst, realm, cred);
155         if (ret != KSUCCESS)
156             return ret;
157
158         des_key_sched(&cred->session, schedule);
159
160         ret = krb_check_auth (&buf, checksum, msg_data, &cred->session, 
161                               schedule, laddr, faddr);
162         if (ret != KSUCCESS)
163             return ret;
164     }
165     return KSUCCESS;
166 }