~ubuntu-branches/ubuntu/precise/krb5/precise-updates

« back to all changes in this revision

Viewing changes to src/plugins/preauth/securid_sam2/securid_sam2_main.c

  • Committer: Package Import Robot
  • Author(s): Sam Hartman
  • Date: 2011-12-01 19:34:41 UTC
  • mfrom: (28.1.14 sid)
  • Revision ID: package-import@ubuntu.com-20111201193441-9tipg3aru1jsidyv
Tags: 1.10+dfsg~alpha1-6
* Fix segfault with unknown hostnames in krb5_sname_to_principal,
  Closes: #650671
* Indicate that this library breaks libsmbclient versions that depend on
  krb5_locate_kdc, Closes: #650603, #650611

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 
2
/* plugins/preauth/securid_sam2/securid_sam2_main.c */
2
3
/*
3
 
 * plugins/preauth/securid_sam2/securid_sam2_main.c
4
 
 *
5
4
 * Copyright (C) 2009, 2010 by the Massachusetts Institute of Technology.
6
5
 * All rights reserved.
7
6
 *
23
22
 * M.I.T. makes no representations about the suitability of
24
23
 * this software for any purpose.  It is provided "as is" without express
25
24
 * or implied warranty.
26
 
 *
 
25
 */
 
26
/*
27
27
 * Copyright (c) 2002 Naval Research Laboratory (NRL/CCS)
28
28
 *
29
29
 * Permission to use, copy, modify and distribute this software and its
34
34
 * NRL ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" CONDITION AND
35
35
 * DISCLAIMS ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER
36
36
 * RESULTING FROM THE USE OF THIS SOFTWARE.
37
 
 *
38
37
 */
39
38
 
40
39
#include <k5-int.h>
62
61
    krb5_error_code retval;
63
62
 
64
63
    if (db_entry)
65
 
       *db_entry = NULL;
 
64
        *db_entry = NULL;
66
65
    retval = krb5_copy_principal(context, client, &newp);
67
66
    if (retval) {
68
 
        com_err("krb5kdc", retval,
69
 
                               "copying client name for preauth probe");
 
67
        com_err("krb5kdc", retval, "copying client name for preauth probe");
70
68
        return retval;
71
69
    }
72
70
 
73
71
    probeslot = krb5_princ_size(context, newp)++;
74
72
    ptr = realloc(krb5_princ_name(context, newp),
75
73
                  krb5_princ_size(context, newp) * sizeof(krb5_data));
76
 
   if (ptr == NULL) {
77
 
       retval = ENOMEM;
78
 
       goto cleanup;
79
 
   }
80
 
   krb5_princ_name(context, newp) = ptr;
81
 
 
82
 
   for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
83
 
       if (*sam_type && *sam_type != sam_ptr->sam_type)
84
 
           continue;
85
 
 
86
 
       krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name;
87
 
       krb5_princ_component(context,newp,probeslot)->length =
88
 
           strlen(sam_ptr->name);
89
 
       retval = krb5_db_get_principal(context, newp, 0, &assoc);
90
 
       if (!retval)
91
 
           break;
92
 
   }
 
74
    if (ptr == NULL) {
 
75
        retval = ENOMEM;
 
76
        goto cleanup;
 
77
    }
 
78
    krb5_princ_name(context, newp) = ptr;
 
79
 
 
80
    for(sam_ptr = sam_inst_map; sam_ptr->name; sam_ptr++) {
 
81
        if (*sam_type && *sam_type != sam_ptr->sam_type)
 
82
            continue;
 
83
 
 
84
        krb5_princ_component(context,newp,probeslot)->data = sam_ptr->name;
 
85
        krb5_princ_component(context,newp,probeslot)->length =
 
86
            strlen(sam_ptr->name);
 
87
        retval = krb5_db_get_principal(context, newp, 0, &assoc);
 
88
        if (!retval)
 
89
            break;
 
90
    }
93
91
cleanup:
94
 
   if (ptr) {
95
 
       krb5_princ_component(context,newp,probeslot)->data = 0;
96
 
       krb5_princ_component(context,newp,probeslot)->length = 0;
97
 
       krb5_free_principal(context, newp);
98
 
   }
99
 
   if (probeslot)
100
 
       krb5_princ_size(context, newp)--;
101
 
   if (retval)
102
 
       return retval;
103
 
   if (sam_ptr->sam_type)  {
104
 
       /* Found entry of type sam_ptr->sam_type */
105
 
       if (sam_type)
106
 
           *sam_type = sam_ptr->sam_type;
107
 
       if (db_entry)
108
 
           *db_entry = assoc;
109
 
       else
110
 
           krb5_db_free_principal(context, assoc);
111
 
       return 0;
112
 
   } else {
113
 
       return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
114
 
   }
 
92
    if (ptr) {
 
93
        krb5_princ_component(context,newp,probeslot)->data = 0;
 
94
        krb5_princ_component(context,newp,probeslot)->length = 0;
 
95
        krb5_free_principal(context, newp);
 
96
    }
 
97
    if (probeslot)
 
98
        krb5_princ_size(context, newp)--;
 
99
    if (retval)
 
100
        return retval;
 
101
    if (sam_ptr->sam_type)  {
 
102
        /* Found entry of type sam_ptr->sam_type */
 
103
        if (sam_type)
 
104
            *sam_type = sam_ptr->sam_type;
 
105
        if (db_entry)
 
106
            *db_entry = assoc;
 
107
        else
 
108
            krb5_db_free_principal(context, assoc);
 
109
        return 0;
 
110
    } else {
 
111
        return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
 
112
    }
115
113
}
116
114
 
117
115
static krb5_error_code
118
116
kdc_include_padata(krb5_context context, krb5_kdc_req *request,
119
 
                   struct _krb5_db_entry_new *client,
120
 
                   struct _krb5_db_entry_new *server,
121
 
                   preauth_get_entry_data_proc get_entry_proc,
122
 
                   void *pa_module_context, krb5_pa_data *pa_data)
 
117
                   krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock,
 
118
                   krb5_kdcpreauth_moddata moddata, krb5_pa_data *pa_data)
123
119
{
124
120
    krb5_error_code retval;
125
 
    krb5_data *client_keys_data = NULL;
126
121
    krb5_keyblock *client_key = NULL;
127
122
    krb5_sam_challenge_2 sc2;
128
123
    krb5_sam_challenge_2_body sc2b;
129
124
    int sam_type = 0;             /* unknown */
130
 
    krb5_db_entry *sam_db_entry = NULL;
 
125
    krb5_db_entry *sam_db_entry = NULL, *client;
131
126
    krb5_data *encoded_challenge = NULL;
132
127
 
133
128
    memset(&sc2, 0, sizeof(sc2));
135
130
    sc2b.magic = KV5M_SAM_CHALLENGE_2;
136
131
    sc2b.sam_type = sam_type;
137
132
 
 
133
    client = cb->client_entry(context, rock);
138
134
    retval = sam_get_db_entry(context, client->princ, &sam_type,
139
135
                              &sam_db_entry);
140
136
    if (retval)
141
137
        return retval;
142
 
    retval = get_entry_proc(context, request, client,
143
 
                            krb5plugin_preauth_keys, &client_keys_data);
 
138
    retval = cb->client_keys(context, rock, &client_key);
144
139
    if (retval)
145
140
        goto cleanup;
146
 
    client_key = (krb5_keyblock *) client_keys_data->data;
147
141
    if (client_key->enctype == 0) {
148
142
        retval = KRB5KDC_ERR_ETYPE_NOSUPP;
149
 
        com_err("krb5kdc", retval, "No client keys found in processing SAM2 challenge");
 
143
        com_err("krb5kdc", retval,
 
144
                "No client keys found in processing SAM2 challenge");
150
145
        goto cleanup;
151
146
    }
152
147
 
171
166
        retval = encode_krb5_sam_challenge_2(&sc2, &encoded_challenge);
172
167
        if (retval) {
173
168
            com_err("krb5kdc", retval,
174
 
                                   "while encoding SECURID SAM_CHALLENGE_2");
 
169
                    "while encoding SECURID SAM_CHALLENGE_2");
175
170
            goto cleanup;
176
171
        }
177
172
 
193
188
    krb5_free_data(context, encoded_challenge);
194
189
    if (sam_db_entry)
195
190
        krb5_db_free_principal(context, sam_db_entry);
196
 
    if (client_keys_data) {
197
 
        while (client_key->enctype) {
198
 
            krb5_free_keyblock_contents(context, client_key);
199
 
            client_key++;
200
 
        }
201
 
        krb5_free_data(context, client_keys_data);
202
 
    }
 
191
    cb->free_keys(context, rock, client_key);
203
192
    return retval;
204
193
}
205
194
 
206
 
static krb5_error_code
207
 
kdc_verify_preauth(krb5_context context, struct _krb5_db_entry_new *client,
208
 
                   krb5_data *req_pkt, krb5_kdc_req *request,
209
 
                   krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa_data,
210
 
                   preauth_get_entry_data_proc get_entry_proc,
211
 
                   void *pa_module_context, void **opaque,
212
 
                   krb5_data **e_data, krb5_authdata ***authz_data)
 
195
static void
 
196
kdc_verify_preauth(krb5_context context, krb5_data *req_pkt,
 
197
                   krb5_kdc_req *request, krb5_enc_tkt_part *enc_tkt_reply,
 
198
                   krb5_pa_data *pa_data, krb5_kdcpreauth_callbacks cb,
 
199
                   krb5_kdcpreauth_rock rock, krb5_kdcpreauth_moddata moddata,
 
200
                   krb5_kdcpreauth_verify_respond_fn respond, void *arg)
213
201
{
214
202
    krb5_error_code retval, saved_retval = 0;
215
203
    krb5_sam_response_2 *sr2 = NULL;
216
 
    krb5_data scratch, *scratch2;
 
204
    krb5_data scratch, *scratch2, *e_data = NULL;
217
205
    char *client_name = NULL;
218
206
    krb5_sam_challenge_2 *out_sc2 = NULL;
 
207
    krb5_db_entry *client = cb->client_entry(context, rock);
219
208
 
220
209
    scratch.data = (char *) pa_data->contents;
221
210
    scratch.length = pa_data->length;
226
215
 
227
216
    retval = decode_krb5_sam_response_2(&scratch, &sr2);
228
217
    if (retval) {
229
 
        com_err("krb5kdc",  retval, "while decoding "
230
 
                               "SAM_RESPONSE_2 in verify_sam_response_2");
 
218
        com_err("krb5kdc",  retval,
 
219
                "while decoding SAM_RESPONSE_2 in verify_sam_response_2");
231
220
        sr2 = NULL;
232
221
        goto cleanup;
233
222
    }
247
236
        break;
248
237
    }
249
238
 
250
 
  /*
251
 
   * It is up to the method-specific verify routine to set the ticket flags to
252
 
   * indicate TKT_FLG_HW_AUTH and/or TKT_FLG_PRE_AUTH.  Some methods may
253
 
   * require more than one round of dialog with the client and must return
254
 
   * successfully from their verify routine.  If does not set the TGT flags,
255
 
   * the required_preauth conditions will not be met and it will try again to
256
 
   * get enough preauth data from the client.  Do not set TGT flags here.
257
 
   */
 
239
    /*
 
240
     * It is up to the method-specific verify routine to set the
 
241
     * ticket flags to indicate TKT_FLG_HW_AUTH and/or
 
242
     * TKT_FLG_PRE_AUTH.  Some methods may require more than one round
 
243
     * of dialog with the client and must return successfully from
 
244
     * their verify routine.  If does not set the TGT flags, the
 
245
     * required_preauth conditions will not be met and it will try
 
246
     * again to get enough preauth data from the client.  Do not set
 
247
     * TGT flags here.
 
248
     */
258
249
cleanup:
259
 
    /*Note that e_data is an output even in error conditions. If we
260
 
      successfully encode the output e_data, we return whatever error
261
 
      is received above. Otherwise we return the encoding error.*/
 
250
    /*
 
251
     * Note that e_data is an output even in error conditions.  If we
 
252
     * successfully encode the output e_data, we return whatever error is
 
253
     * received above.  Otherwise we return the encoding error.
 
254
     */
262
255
    saved_retval = retval;
263
256
    if (out_sc2) {
264
257
        krb5_pa_data pa_out;
272
265
            goto encode_error;
273
266
        pa_out.contents = (krb5_octet *) scratch2->data;
274
267
        pa_out.length = scratch2->length;
275
 
        retval = encode_krb5_padata_sequence(pa_array, e_data);
 
268
        retval = encode_krb5_padata_sequence(pa_array, &e_data);
276
269
        krb5_free_data(context, scratch2);
277
270
    }
278
271
encode_error:
280
273
    free(client_name);
281
274
    if (retval == 0)
282
275
        retval = saved_retval;
283
 
    return retval;
 
276
 
 
277
    (*respond)(arg, retval, NULL, NULL, NULL);
284
278
}
285
279
 
286
280
 
293
287
krb5_preauthtype supported_pa_types[] = {
294
288
    KRB5_PADATA_SAM_RESPONSE_2, 0};
295
289
 
296
 
struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
297
 
    "SAM2",
298
 
    &supported_pa_types[0],
299
 
    NULL,
300
 
    NULL,
301
 
    kdc_preauth_flags,
302
 
    kdc_include_padata,
303
 
    kdc_verify_preauth,
304
 
    NULL,
305
 
    NULL
306
 
};
 
290
krb5_error_code
 
291
kdcpreauth_securid_sam2_initvt(krb5_context context, int maj_ver, int min_ver,
 
292
                               krb5_plugin_vtable vtable);
 
293
 
 
294
krb5_error_code
 
295
kdcpreauth_securid_sam2_initvt(krb5_context context, int maj_ver, int min_ver,
 
296
                               krb5_plugin_vtable vtable)
 
297
{
 
298
    krb5_kdcpreauth_vtable vt;
 
299
 
 
300
    if (maj_ver != 1)
 
301
        return KRB5_PLUGIN_VER_NOTSUPP;
 
302
    vt = (krb5_kdcpreauth_vtable)vtable;
 
303
    vt->name = "securid_sam2";
 
304
    vt->pa_type_list = supported_pa_types;
 
305
    vt->flags = kdc_preauth_flags;
 
306
    vt->edata = kdc_include_padata;
 
307
    vt->verify = kdc_verify_preauth;
 
308
    return 0;
 
309
}