~ubuntu-branches/ubuntu/oneiric/nfs-utils/oneiric

« back to all changes in this revision

Viewing changes to utils/gssd/svcgssd_proc.c

  • Committer: Steve Langasek
  • Date: 2010-06-04 09:53:57 UTC
  • mfrom: (14.1.5 sid)
  • Revision ID: vorlon@debian.org-20100604095357-zbu3na972v3nmgvg
mergeĀ versionĀ 1:1.2.2-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
#include "gss_util.h"
57
57
#include "err_util.h"
58
58
#include "context.h"
 
59
#include "gss_oids.h"
59
60
 
60
61
extern char * mech2file(gss_OID mech);
61
62
#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
73
74
static int
74
75
do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
75
76
                gss_OID mech, gss_buffer_desc *context_token,
76
 
                int32_t endtime)
 
77
                int32_t endtime, char *client_name)
77
78
{
78
79
        FILE *f;
79
80
        int i;
98
99
        qword_printint(f, cred->cr_gid);
99
100
        qword_printint(f, cred->cr_ngroups);
100
101
        printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d (%d from now), "
101
 
                 "uid: %d, gid: %d, num aux grps: %d:\n",
 
102
                 "clnt: %s, uid: %d, gid: %d, num aux grps: %d:\n",
102
103
                 fname, out_handle->length, context_token->length,
103
104
                 endtime, endtime - time(0),
 
105
                 client_name ? client_name : "<null>",
104
106
                 cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
105
107
        for (i=0; i < cred->cr_ngroups; i++) {
106
108
                qword_printint(f, cred->cr_groups[i]);
108
110
        }
109
111
        qword_print(f, fname);
110
112
        qword_printhex(f, context_token->value, context_token->length);
 
113
        if (client_name)
 
114
                qword_print(f, client_name);
111
115
        err = qword_eol(f);
112
116
        if (err) {
113
117
                printerr(1, "WARNING: error writing to downcall channel "
307
311
}
308
312
#endif
309
313
 
 
314
static int
 
315
get_krb5_hostbased_name (gss_buffer_desc *name, char **hostbased_name)
 
316
{
 
317
        char *p, *sname = NULL;
 
318
        if (strchr(name->value, '@') && strchr(name->value, '/')) {
 
319
                if ((sname = calloc(name->length, 1)) == NULL) {
 
320
                        printerr(0, "ERROR: get_krb5_hostbased_name failed "
 
321
                                 "to allocate %d bytes\n", name->length);
 
322
                        return -1;
 
323
                }
 
324
                /* read in name and instance and replace '/' with '@' */
 
325
                sscanf(name->value, "%[^@]", sname);
 
326
                p = strrchr(sname, '/');
 
327
                if (p == NULL) {    /* The '@' preceeded the '/' */
 
328
                        free(sname);
 
329
                        return -1;
 
330
                }
 
331
                *p = '@';
 
332
        }
 
333
        *hostbased_name = sname;
 
334
        return 0;
 
335
}
 
336
 
 
337
static int
 
338
get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
 
339
                          char **hostbased_name)
 
340
{
 
341
        u_int32_t       maj_stat, min_stat;
 
342
        gss_buffer_desc name;
 
343
        gss_OID         name_type = GSS_C_NO_OID;
 
344
        char            *cname;
 
345
        int             res = -1;
 
346
 
 
347
        *hostbased_name = NULL;     /* preset in case we fail */
 
348
 
 
349
        /* Get the client's gss authenticated name */
 
350
        maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
 
351
        if (maj_stat != GSS_S_COMPLETE) {
 
352
                pgsserr("get_hostbased_client_name: gss_display_name",
 
353
                        maj_stat, min_stat, mech);
 
354
                goto out_err;
 
355
        }
 
356
        if (name.length >= 0xffff) {        /* don't overflow */
 
357
                printerr(0, "ERROR: get_hostbased_client_name: "
 
358
                         "received gss_name is too long (%d bytes)\n",
 
359
                         name.length);
 
360
                goto out_rel_buf;
 
361
        }
 
362
 
 
363
        /* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
 
364
         * an NT_HOSTBASED_SERVICE name */
 
365
        if (g_OID_equal(&krb5oid, mech)) {
 
366
                if (get_krb5_hostbased_name(&name, &cname) == 0)
 
367
                        *hostbased_name = cname;
 
368
        }
 
369
 
 
370
        /* No support for SPKM3, just print a warning (for now) */
 
371
        if (g_OID_equal(&spkm3oid, mech)) {
 
372
                printerr(1, "WARNING: get_hostbased_client_name: "
 
373
                         "no hostbased_name support for SPKM3\n");
 
374
        }
 
375
 
 
376
        res = 0;
 
377
out_rel_buf:
 
378
        gss_release_buffer(&min_stat, &name);
 
379
out_err:
 
380
        return res;
 
381
}
 
382
 
310
383
void
311
384
handle_nullreq(FILE *f) {
312
385
        /* XXX initialize to a random integer to reduce chances of unnecessary
325
398
                                null_token = {.value = NULL};
326
399
        u_int32_t               ret_flags;
327
400
        gss_ctx_id_t            ctx = GSS_C_NO_CONTEXT;
328
 
        gss_name_t              client_name;
 
401
        gss_name_t              client_name = NULL;
329
402
        gss_OID                 mech = GSS_C_NO_OID;
330
403
        u_int32_t               maj_stat = GSS_S_FAILURE, min_stat = 0;
331
404
        u_int32_t               ignore_min_stat;
334
407
        static int              lbuflen = 0;
335
408
        static char             *cp;
336
409
        int32_t                 ctx_endtime;
 
410
        char                    *hostbased_name = NULL;
337
411
 
338
412
        printerr(1, "handling null request\n");
339
413
 
396
470
        if (get_ids(client_name, mech, &cred)) {
397
471
                /* get_ids() prints error msg */
398
472
                maj_stat = GSS_S_BAD_NAME; /* XXX ? */
399
 
                gss_release_name(&ignore_min_stat, &client_name);
400
 
                goto out_err;
401
 
        }
402
 
        gss_release_name(&ignore_min_stat, &client_name);
403
 
 
 
473
                goto out_err;
 
474
        }
 
475
        if (get_hostbased_client_name(client_name, mech, &hostbased_name)) {
 
476
                /* get_hostbased_client_name() prints error msg */
 
477
                maj_stat = GSS_S_BAD_NAME; /* XXX ? */
 
478
                goto out_err;
 
479
        }
404
480
 
405
481
        /* Context complete. Pass handle_seq in out_handle to use
406
482
         * for context lookup in the kernel. */
419
495
        /* We no longer need the gss context */
420
496
        gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
421
497
 
422
 
        do_svc_downcall(&out_handle, &cred, mech, &ctx_token, ctx_endtime);
 
498
        do_svc_downcall(&out_handle, &cred, mech, &ctx_token, ctx_endtime,
 
499
                        hostbased_name);
423
500
continue_needed:
424
501
        send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
425
502
                        &out_handle, &out_tok);
428
505
                free(ctx_token.value);
429
506
        if (out_tok.value != NULL)
430
507
                gss_release_buffer(&ignore_min_stat, &out_tok);
 
508
        if (client_name)
 
509
                gss_release_name(&ignore_min_stat, &client_name);
 
510
        free(hostbased_name);
431
511
        printerr(1, "finished handling null request\n");
432
512
        return;
433
513