add const where appropriate in function declarations
[krb5.git] / src / lib / krb5 / krb / mk_req_ext.c
1 /*
2  * $Source$
3  * $Author$
4  *
5  * Copyright 1990 by the Massachusetts Institute of Technology.
6  *
7  * For copying and distribution information, please see the file
8  * <krb5/mit-copyright.h>.
9  *
10  * krb5_mk_req_extended()
11  */
12
13 #if !defined(lint) && !defined(SABER)
14 static char mk_req_ext_c[] =
15 "$Id$";
16 #endif  /* !lint & !SABER */
17
18 #include <krb5/copyright.h>
19 #include <krb5/krb5.h>
20 #include <krb5/krb5_err.h>
21 #include <krb5/asn1.h>
22
23 #include <krb5/libos.h>
24 #include <stdio.h>
25 #include <krb5/libos-proto.h>
26
27 #include <krb5/ext-proto.h>
28 #include <errno.h>
29
30 /*
31  Formats a KRB_AP_REQ message into outbuf, with more complete options than
32  krb_mk_req.
33
34  outbuf, ap_req_options, checksum, and ccache are used in the
35  same fashion as for krb5_mk_req.
36
37  creds is used to supply the credentials (ticket and session key) needed
38  to form the request.
39
40  if creds->ticket has no data (length == 0), then a ticket is obtained
41  from either the cache or the TGS, passing creds to krb5_get_credentials().
42  kdc_options specifies the options requested for the ticket to be used.
43  If a ticket with appropriate flags is not found in the cache, then these
44  options are passed on in a request to an appropriate KDC.
45
46  ap_req_options specifies the KRB_AP_REQ options desired.
47
48  if ap_req_options specifies AP_OPTS_USE_SESSION_KEY, then creds->ticket
49  must contain the appropriate ENC-TKT-IN-SKEY ticket.
50
51  checksum specifies the checksum to be used in the authenticator.
52
53  The outbuf buffer storage is allocated, and should be freed by the
54  caller when finished.
55
56  returns system errors
57 */
58 static krb5_error_code generate_authenticator PROTOTYPE((krb5_authenticator *,
59                                                          const krb5_creds *,
60                                                          const krb5_checksum *));
61
62 krb5_error_code
63 krb5_mk_req_extended(ap_req_options, checksum, times, kdc_options, ccache,
64                      creds, outbuf)
65 const krb5_flags ap_req_options;
66 const krb5_checksum *checksum;
67 const krb5_ticket_times *times;
68 const krb5_flags kdc_options;
69 krb5_ccache ccache;
70 krb5_creds *creds;
71 krb5_data *outbuf;
72 {
73     krb5_error_code retval;
74     krb5_ap_req request;
75     krb5_authenticator authent;
76     krb5_data *scratch;
77     krb5_enctype etype;
78     krb5_encrypt_block eblock;
79
80     if ((ap_req_options & AP_OPTS_USE_SESSION_KEY) &&
81         !creds->ticket.length)
82         return(KRB5_NO_TKT_SUPPLIED);
83
84     if (!creds->ticket.length) {
85         /* go get creds */
86         creds->times = *times;          /* XXX do we need times? */
87         if (retval = krb5_get_credentials(kdc_options,
88                                           ccache,
89                                           creds))
90             return(retval);
91     }
92     /* verify a valid etype is available */
93     if (!valid_keytype(creds->keyblock.keytype))
94         return KRB5_PROG_KEYTYPE_NOSUPP;
95
96     etype = krb5_keytype_array[creds->keyblock.keytype]->system->proto_enctype;
97
98     if (!valid_etype(etype))
99         return KRB5_PROG_ETYPE_NOSUPP;
100
101     request.ap_options = ap_req_options;
102     /* we need a native ticket */
103     if (retval = krb5_decode_ticket(&creds->ticket, &request.ticket))
104         return(retval);                 /* XXX who cleans up creds? */
105
106 #define cleanup_ticket() krb5_free_ticket(request.ticket)
107     if (retval = generate_authenticator(&authent, creds, checksum)) {
108         cleanup_ticket();
109         return retval;
110     }
111     /* encode it before encrypting */
112     retval = encode_krb5_authenticator(&authent, &scratch);
113     cleanup_ticket();
114     if (retval)
115         return(retval);
116
117 #define cleanup_scratch() { (void) bzero(scratch->data, scratch->length); krb5_free_data(scratch); }
118
119     /* put together an eblock for this encryption */
120
121     eblock.crypto_entry = krb5_csarray[etype]->system;
122     request.authenticator.length = krb5_encrypt_size(scratch->length,
123                                                      eblock.crypto_entry);
124     if (!(request.authenticator.data = malloc(request.authenticator.length))) {
125         retval = ENOMEM;
126         goto clean_scratch;
127     }
128
129 #define cleanup_encpart() {(void) bzero(request.authenticator.data, request.authenticator.length); free(request.authenticator.data); request.authenticator.length = 0; request.authenticator.data = 0;}
130
131     /* do any necessary key pre-processing */
132     if (retval = (*eblock.crypto_entry->process_key)(&eblock,
133                                                      &creds->keyblock)) {
134         goto clean_encpart;
135     }
136
137 #define cleanup_prockey() {(void) (*eblock.crypto_entry->finish_key)(&eblock);}
138
139     /* call the encryption routine */
140     if (retval =
141         (*eblock.crypto_entry->encrypt_func)((krb5_pointer) scratch->data,
142                                              (krb5_pointer) request.authenticator.data,
143                                              scratch->length, &eblock)) {
144         goto clean_prockey;
145     }
146
147     /* authenticator now assembled-- do some cleanup */
148     cleanup_scratch();
149
150     if (retval = (*eblock.crypto_entry->finish_key)(&eblock)) {
151         cleanup_encpart();
152         return retval;
153     }
154
155     retval = encode_krb5_ap_req(&request, &outbuf);
156     cleanup_encpart();
157     if (retval)
158         return(retval);
159
160  clean_prockey:
161     cleanup_prockey();
162  clean_encpart:
163     cleanup_encpart();
164  clean_scratch:
165     cleanup_scratch();
166     cleanup_ticket();
167
168     return retval;
169 }
170
171 static krb5_error_code
172 generate_authenticator(authent, creds, cksum)
173 krb5_authenticator *authent;
174 const krb5_creds *creds;
175 const krb5_checksum *cksum;
176 {
177     authent->client = creds->client;
178     authent->checksum = cksum;
179     return(krb5_ms_timeofday(&authent->ctime, &authent->cmsec));
180 }