~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/krb5/ticket.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
 
3
 * (Royal Institute of Technology, Stockholm, Sweden).
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 *
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * 3. Neither the name of the Institute nor the names of its contributors
 
18
 *    may be used to endorse or promote products derived from this software
 
19
 *    without specific prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
31
 * SUCH DAMAGE.
 
32
 */
 
33
 
 
34
#include "krb5_locl.h"
 
35
 
 
36
RCSID("$Id$");
 
37
 
 
38
krb5_error_code KRB5_LIB_FUNCTION
 
39
krb5_free_ticket(krb5_context context,
 
40
                 krb5_ticket *ticket)
 
41
{
 
42
    free_EncTicketPart(&ticket->ticket);
 
43
    krb5_free_principal(context, ticket->client);
 
44
    krb5_free_principal(context, ticket->server);
 
45
    free(ticket);
 
46
    return 0;
 
47
}
 
48
 
 
49
krb5_error_code KRB5_LIB_FUNCTION
 
50
krb5_copy_ticket(krb5_context context,
 
51
                 const krb5_ticket *from,
 
52
                 krb5_ticket **to)
 
53
{
 
54
    krb5_error_code ret;
 
55
    krb5_ticket *tmp;
 
56
 
 
57
    *to = NULL;
 
58
    tmp = malloc(sizeof(*tmp));
 
59
    if(tmp == NULL) {
 
60
        krb5_set_error_message(context, ENOMEM,
 
61
                               N_("malloc: out of memory", ""));
 
62
        return ENOMEM;
 
63
    }
 
64
    if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
 
65
        free(tmp);
 
66
        return ret;
 
67
    }
 
68
    ret = krb5_copy_principal(context, from->client, &tmp->client);
 
69
    if(ret){
 
70
        free_EncTicketPart(&tmp->ticket);
 
71
        free(tmp);
 
72
        return ret;
 
73
    }
 
74
    ret = krb5_copy_principal(context, from->server, &tmp->server);
 
75
    if(ret){
 
76
        krb5_free_principal(context, tmp->client);
 
77
        free_EncTicketPart(&tmp->ticket);
 
78
        free(tmp);
 
79
        return ret;
 
80
    }
 
81
    *to = tmp;
 
82
    return 0;
 
83
}
 
84
 
 
85
krb5_error_code KRB5_LIB_FUNCTION
 
86
krb5_ticket_get_client(krb5_context context,
 
87
                       const krb5_ticket *ticket,
 
88
                       krb5_principal *client)
 
89
{
 
90
    return krb5_copy_principal(context, ticket->client, client);
 
91
}
 
92
 
 
93
krb5_error_code KRB5_LIB_FUNCTION
 
94
krb5_ticket_get_server(krb5_context context,
 
95
                       const krb5_ticket *ticket,
 
96
                       krb5_principal *server)
 
97
{
 
98
    return krb5_copy_principal(context, ticket->server, server);
 
99
}
 
100
 
 
101
time_t KRB5_LIB_FUNCTION
 
102
krb5_ticket_get_endtime(krb5_context context,
 
103
                        const krb5_ticket *ticket)
 
104
{
 
105
    return ticket->ticket.endtime;
 
106
}
 
107
 
 
108
/**
 
109
 * Get the flags from the Kerberos ticket
 
110
 *
 
111
 * @param context Kerberos context
 
112
 * @param ticket Kerberos ticket
 
113
 *
 
114
 * @return ticket flags
 
115
 *
 
116
 * @ingroup krb5_ticket
 
117
 */
 
118
unsigned long
 
119
krb5_ticket_get_flags(krb5_context context,
 
120
                      const krb5_ticket *ticket)
 
121
{
 
122
    return TicketFlags2int(ticket->ticket.flags);
 
123
}
 
124
 
 
125
static int
 
126
find_type_in_ad(krb5_context context,
 
127
                int type,
 
128
                krb5_data *data,
 
129
                krb5_boolean *found,
 
130
                krb5_boolean failp,
 
131
                krb5_keyblock *sessionkey,
 
132
                const AuthorizationData *ad,
 
133
                int level)
 
134
{
 
135
    krb5_error_code ret = 0;
 
136
    int i;
 
137
 
 
138
    if (level > 9) {
 
139
        ret = ENOENT; /* XXX */
 
140
        krb5_set_error_message(context, ret,
 
141
                               N_("Authorization data nested deeper "
 
142
                                  "then %d levels, stop searching", ""),
 
143
                               level);
 
144
        goto out;
 
145
    }
 
146
 
 
147
    /*
 
148
     * Only copy out the element the first time we get to it, we need
 
149
     * to run over the whole authorization data fields to check if
 
150
     * there are any container clases we need to care about.
 
151
     */
 
152
    for (i = 0; i < ad->len; i++) {
 
153
        if (!*found && ad->val[i].ad_type == type) {
 
154
            ret = der_copy_octet_string(&ad->val[i].ad_data, data);
 
155
            if (ret) {
 
156
                krb5_set_error_message(context, ret,
 
157
                                       N_("malloc: out of memory", ""));
 
158
                goto out;
 
159
            }
 
160
            *found = TRUE;
 
161
            continue;
 
162
        }
 
163
        switch (ad->val[i].ad_type) {
 
164
        case KRB5_AUTHDATA_IF_RELEVANT: {
 
165
            AuthorizationData child;
 
166
            ret = decode_AuthorizationData(ad->val[i].ad_data.data,
 
167
                                           ad->val[i].ad_data.length,
 
168
                                           &child,
 
169
                                           NULL);
 
170
            if (ret) {
 
171
                krb5_set_error_message(context, ret,
 
172
                                       N_("Failed to decode "
 
173
                                          "IF_RELEVANT with %d", ""),
 
174
                                       (int)ret);
 
175
                goto out;
 
176
            }
 
177
            ret = find_type_in_ad(context, type, data, found, FALSE,
 
178
                                  sessionkey, &child, level + 1);
 
179
            free_AuthorizationData(&child);
 
180
            if (ret)
 
181
                goto out;
 
182
            break;
 
183
        }
 
184
#if 0 /* XXX test */
 
185
        case KRB5_AUTHDATA_KDC_ISSUED: {
 
186
            AD_KDCIssued child;
 
187
 
 
188
            ret = decode_AD_KDCIssued(ad->val[i].ad_data.data,
 
189
                                      ad->val[i].ad_data.length,
 
190
                                      &child,
 
191
                                      NULL);
 
192
            if (ret) {
 
193
                krb5_set_error_message(context, ret,
 
194
                                       N_("Failed to decode "
 
195
                                          "AD_KDCIssued with %d", ""),
 
196
                                       ret);
 
197
                goto out;
 
198
            }
 
199
            if (failp) {
 
200
                krb5_boolean valid;
 
201
                krb5_data buf;
 
202
                size_t len;
 
203
 
 
204
                ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length,
 
205
                                   &child.elements, &len, ret);
 
206
                if (ret) {
 
207
                    free_AD_KDCIssued(&child);
 
208
                    krb5_clear_error_message(context);
 
209
                    goto out;
 
210
                }
 
211
                if(buf.length != len)
 
212
                    krb5_abortx(context, "internal error in ASN.1 encoder");
 
213
 
 
214
                ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf,
 
215
                                             &child.ad_checksum, &valid);
 
216
                krb5_data_free(&buf);
 
217
                if (ret) {
 
218
                    free_AD_KDCIssued(&child);
 
219
                    goto out;
 
220
                }
 
221
                if (!valid) {
 
222
                    krb5_clear_error_message(context);
 
223
                    ret = ENOENT;
 
224
                    free_AD_KDCIssued(&child);
 
225
                    goto out;
 
226
                }
 
227
            }
 
228
            ret = find_type_in_ad(context, type, data, found, failp, sessionkey,
 
229
                                  &child.elements, level + 1);
 
230
            free_AD_KDCIssued(&child);
 
231
            if (ret)
 
232
                goto out;
 
233
            break;
 
234
        }
 
235
#endif
 
236
        case KRB5_AUTHDATA_AND_OR:
 
237
            if (!failp)
 
238
                break;
 
239
            ret = ENOENT; /* XXX */
 
240
            krb5_set_error_message(context, ret,
 
241
                                   N_("Authorization data contains "
 
242
                                      "AND-OR element that is unknown to the "
 
243
                                      "application", ""));
 
244
            goto out;
 
245
        default:
 
246
            if (!failp)
 
247
                break;
 
248
            ret = ENOENT; /* XXX */
 
249
            krb5_set_error_message(context, ret,
 
250
                                   N_("Authorization data contains "
 
251
                                      "unknown type (%d) ", ""),
 
252
                                   ad->val[i].ad_type);
 
253
            goto out;
 
254
        }
 
255
    }
 
256
out:
 
257
    if (ret) {
 
258
        if (*found) {
 
259
            krb5_data_free(data);
 
260
            *found = 0;
 
261
        }
 
262
    }
 
263
    return ret;
 
264
}
 
265
 
 
266
/*
 
267
 * Extract the authorization data type of `type' from the
 
268
 * 'ticket'. Store the field in `data'. This function is to use for
 
269
 * kerberos applications.
 
270
 */
 
271
 
 
272
krb5_error_code KRB5_LIB_FUNCTION
 
273
krb5_ticket_get_authorization_data_type(krb5_context context,
 
274
                                        krb5_ticket *ticket,
 
275
                                        int type,
 
276
                                        krb5_data *data)
 
277
{
 
278
    AuthorizationData *ad;
 
279
    krb5_error_code ret;
 
280
    krb5_boolean found = FALSE;
 
281
 
 
282
    krb5_data_zero(data);
 
283
 
 
284
    ad = ticket->ticket.authorization_data;
 
285
    if (ticket->ticket.authorization_data == NULL) {
 
286
        krb5_set_error_message(context, ENOENT,
 
287
                               N_("Ticket have not authorization data", ""));
 
288
        return ENOENT; /* XXX */
 
289
    }
 
290
 
 
291
    ret = find_type_in_ad(context, type, data, &found, TRUE,
 
292
                          &ticket->ticket.key, ad, 0);
 
293
    if (ret)
 
294
        return ret;
 
295
    if (!found) {
 
296
        krb5_set_error_message(context, ENOENT,
 
297
                               N_("Ticket have not "
 
298
                                  "authorization data of type %d", ""),
 
299
                               type);
 
300
        return ENOENT; /* XXX */
 
301
    }
 
302
    return 0;
 
303
}