~ubuntu-branches/ubuntu/oneiric/likewise-open/oneiric

« back to all changes in this revision

Viewing changes to krb5/src/windows/gss/gss-client.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Salley
  • Date: 2010-11-22 12:06:00 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122120600-8lba1fpceot71wlb
Tags: 6.0.0.53010-1
Likewise Open 6.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 1994 by OpenVision Technologies, Inc.
 
3
 * 
 
4
 * Permission to use, copy, modify, distribute, and sell this software
 
5
 * and its documentation for any purpose is hereby granted without fee,
 
6
 * provided that the above copyright notice appears in all copies and
 
7
 * that both that copyright notice and this permission notice appear in
 
8
 * supporting documentation, and that the name of OpenVision not be used
 
9
 * in advertising or publicity pertaining to distribution of the software
 
10
 * without specific, written prior permission. OpenVision makes no
 
11
 * representations about the suitability of this software for any
 
12
 * purpose.  It is provided "as is" without express or implied warranty.
 
13
 * 
 
14
 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
15
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
16
 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
17
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
 
18
 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 
19
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
20
 * PERFORMANCE OF THIS SOFTWARE.
 
21
 */
 
22
/*
 
23
 * Copyright (C) 2004 by the Massachusetts Institute of Technology.
 
24
 * All rights reserved.
 
25
 *
 
26
 * Export of this software from the United States of America may
 
27
 *   require a specific license from the United States Government.
 
28
 *   It is the responsibility of any person or organization contemplating
 
29
 *   export to obtain such a license before exporting.
 
30
 * 
 
31
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
 
32
 * distribute this software and its documentation for any purpose and
 
33
 * without fee is hereby granted, provided that the above copyright
 
34
 * notice appear in all copies and that both that copyright notice and
 
35
 * this permission notice appear in supporting documentation, and that
 
36
 * the name of M.I.T. not be used in advertising or publicity pertaining
 
37
 * to distribution of the software without specific, written prior
 
38
 * permission.  Furthermore if you modify this software you must label
 
39
 * your software as modified software and not distribute it in such a
 
40
 * fashion that it might be confused with the original M.I.T. software.
 
41
 * M.I.T. makes no representations about the suitability of
 
42
 * this software for any purpose.  It is provided "as is" without express
 
43
 * or implied warranty.
 
44
 */
 
45
 
 
46
#include <stdio.h>
 
47
#include <stdlib.h>
 
48
#include <string.h>
 
49
#include <windows.h>
 
50
#include <winsock.h>
 
51
 
 
52
#include <gssapi/gssapi_generic.h>
 
53
#include <gssapi\gssapi_krb5.h>
 
54
#include "gss.h"
 
55
#include "gss-misc.h"
 
56
 
 
57
static int verbose = 1;
 
58
 
 
59
/*
 
60
 * Function: connect_to_server
 
61
 *
 
62
 * Purpose: Opens a TCP connection to the name host and port.
 
63
 *
 
64
 * Arguments:
 
65
 *
 
66
 *      host            (r) the target host name
 
67
 *      port            (r) the target port, in host byte order
 
68
 *
 
69
 * Returns: the established socket file desciptor, or -1 on failure
 
70
 *
 
71
 * Effects:
 
72
 *
 
73
 * The host name is resolved with gethostbyname(), and the socket is
 
74
 * opened and connected.  If an error occurs, an error message is
 
75
 * displayed and -1 is returned.
 
76
 */
 
77
static int connect_to_server(host, port)
 
78
     char *host;
 
79
     u_short port;
 
80
{
 
81
     struct sockaddr_in saddr;
 
82
     struct hostent *hp;
 
83
     int s;
 
84
     
 
85
     if ((hp = gethostbyname(host)) == NULL) {
 
86
          printf("Unknown host: %s\r\n", host);
 
87
          return -1;
 
88
     }
 
89
     
 
90
     saddr.sin_family = hp->h_addrtype;
 
91
     memcpy((char *)&saddr.sin_addr, hp->h_addr, sizeof(saddr.sin_addr));
 
92
     saddr.sin_port = htons(port);
 
93
 
 
94
     if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
 
95
          perror("creating socket");
 
96
          return -1;
 
97
     }
 
98
     if (connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
 
99
          perror("connecting to server");
 
100
          (void) closesocket(s);
 
101
          return -1;
 
102
     }
 
103
     return s;
 
104
}
 
105
 
 
106
/*
 
107
 * Function: client_establish_context
 
108
 *
 
109
 * Purpose: establishes a GSS-API context with a specified service and
 
110
 * returns the context handle
 
111
 *
 
112
 * Arguments:
 
113
 *
 
114
 *      s               (r) an established TCP connection to the service
 
115
 *      service_name    (r) the ASCII service name of the service
 
116
 *      gss_flags       (r) GSS-API delegation flag (if any)
 
117
 *      auth_flag       (r) whether to actually do authentication
 
118
 *      oid             (r) OID of the mechanism to use
 
119
 *      context         (w) the established GSS-API context
 
120
 *      ret_flags       (w) the returned flags from init_sec_context
 
121
 *
 
122
 * Returns: 0 on success, -1 on failure
 
123
 *
 
124
 * Effects:
 
125
 * 
 
126
 * service_name is imported as a GSS-API name and a GSS-API context is
 
127
 * established with the corresponding service; the service should be
 
128
 * listening on the TCP connection s.  The default GSS-API mechanism
 
129
 * is used, and mutual authentication and replay detection are
 
130
 * requested.
 
131
 * 
 
132
 * If successful, the context handle is returned in context.  If
 
133
 * unsuccessful, the GSS-API error messages are displayed on stderr
 
134
 * and -1 is returned.
 
135
 */
 
136
int client_establish_context( int s, 
 
137
                              char *service_name,
 
138
                              OM_uint32 gss_flags, 
 
139
                              int auth_flag,
 
140
                              int v1_format, 
 
141
                              gss_OID oid, 
 
142
                              gss_ctx_id_t *gss_context, 
 
143
                              OM_uint32 *ret_flags)
 
144
{
 
145
    if (auth_flag) {
 
146
        gss_buffer_desc send_tok, recv_tok, *token_ptr;
 
147
        gss_name_t target_name;
 
148
        OM_uint32 maj_stat, min_stat, init_sec_min_stat;
 
149
        int token_flags;
 
150
 
 
151
       /*
 
152
        * Import the name into target_name.  Use send_tok to save
 
153
        * local variable space.
 
154
        */
 
155
        send_tok.value = service_name;
 
156
        send_tok.length = strlen(service_name) ;
 
157
        maj_stat = gss_import_name(&min_stat, &send_tok,
 
158
                                    (gss_OID) gss_nt_service_name, &target_name);
 
159
        if (maj_stat != GSS_S_COMPLETE) {
 
160
            display_status("parsing name", maj_stat, min_stat);
 
161
            return -1;
 
162
        }
 
163
     
 
164
        if (!v1_format) {
 
165
            if (send_token(s, TOKEN_NOOP|TOKEN_CONTEXT_NEXT, empty_token) < 0) {
 
166
                (void) gss_release_name(&min_stat, &target_name);
 
167
                return -1;
 
168
            }
 
169
        }
 
170
 
 
171
       /*
 
172
        * Perform the context-establishement loop.
 
173
        *
 
174
        * On each pass through the loop, token_ptr points to the token
 
175
        * to send to the server (or GSS_C_NO_BUFFER on the first pass).
 
176
        * Every generated token is stored in send_tok which is then
 
177
        * transmitted to the server; every received token is stored in
 
178
        * recv_tok, which token_ptr is then set to, to be processed by
 
179
        * the next call to gss_init_sec_context.
 
180
        * 
 
181
        * GSS-API guarantees that send_tok's length will be non-zero
 
182
        * if and only if the server is expecting another token from us,
 
183
        * and that gss_init_sec_context returns GSS_S_CONTINUE_NEEDED if
 
184
        * and only if the server has another token to send us.
 
185
        */
 
186
 
 
187
        token_ptr = GSS_C_NO_BUFFER;
 
188
        *gss_context = GSS_C_NO_CONTEXT;
 
189
 
 
190
        do {
 
191
            maj_stat =
 
192
                gss_init_sec_context(&init_sec_min_stat,
 
193
                                      GSS_C_NO_CREDENTIAL,
 
194
                                      gss_context,
 
195
                                      target_name,
 
196
                                      oid,
 
197
                                      gss_flags,
 
198
                                      0,
 
199
                                      NULL,     /* no channel bindings */
 
200
                                      token_ptr,
 
201
                                      NULL,     /* ignore mech type */
 
202
                                      &send_tok,
 
203
                                      ret_flags,
 
204
                                      NULL);    /* ignore time_rec */
 
205
 
 
206
            if (token_ptr != GSS_C_NO_BUFFER)
 
207
                free (recv_tok.value);
 
208
 
 
209
            if (send_tok.length != 0) {
 
210
                if (verbose)
 
211
                    printf("Sending init_sec_context token (size=%d)...",
 
212
                            (int) send_tok.length);
 
213
                if (send_token(s, v1_format?0:TOKEN_CONTEXT, &send_tok) < 0) {
 
214
                    (void) gss_release_buffer(&min_stat, &send_tok);
 
215
                    (void) gss_release_name(&min_stat, &target_name);
 
216
                    return -1;
 
217
                }
 
218
            }
 
219
            (void) gss_release_buffer(&min_stat, &send_tok);
 
220
 
 
221
            if (maj_stat!=GSS_S_COMPLETE && maj_stat!=GSS_S_CONTINUE_NEEDED) {
 
222
                display_status("initializing context", maj_stat,
 
223
                                init_sec_min_stat);
 
224
                (void) gss_release_name(&min_stat, &target_name);
 
225
                if (*gss_context != GSS_C_NO_CONTEXT)
 
226
                    gss_delete_sec_context(&min_stat, gss_context,
 
227
                                            GSS_C_NO_BUFFER);
 
228
                return -1;
 
229
            }
 
230
 
 
231
            if (maj_stat == GSS_S_CONTINUE_NEEDED) {
 
232
                if (verbose)
 
233
                    printf("continue needed...");
 
234
                if (recv_token(s, &token_flags, &recv_tok) < 0) {
 
235
                    (void) gss_release_name(&min_stat, &target_name);
 
236
                    return -1;
 
237
                }
 
238
                token_ptr = &recv_tok;
 
239
            }
 
240
            if (verbose)
 
241
                printf("\r\n");
 
242
        } while (maj_stat == GSS_S_CONTINUE_NEEDED);
 
243
 
 
244
        (void) gss_release_name(&min_stat, &target_name);
 
245
    }
 
246
    else {
 
247
        if (send_token(s, TOKEN_NOOP, empty_token) < 0)
 
248
            return -1;
 
249
    }
 
250
 
 
251
    return 0;
 
252
}
 
253
 
 
254
static void read_file(file_name, in_buf)
 
255
    char                *file_name;
 
256
    gss_buffer_t        in_buf;
 
257
{
 
258
    int fd, count;
 
259
    struct stat stat_buf;
 
260
    
 
261
    if ((fd = open(file_name, O_RDONLY, 0)) < 0) {
 
262
        perror("open");
 
263
        printf("Couldn't open file %s\r\n", file_name);
 
264
        exit(1);
 
265
    }
 
266
    if (fstat(fd, &stat_buf) < 0) {
 
267
        perror("fstat");
 
268
        exit(1);
 
269
    }
 
270
    in_buf->length = stat_buf.st_size;
 
271
 
 
272
    if (in_buf->length == 0) {
 
273
        in_buf->value = NULL;
 
274
        return;
 
275
    }
 
276
 
 
277
    if ((in_buf->value = malloc(in_buf->length)) == 0) {
 
278
        printf("Couldn't allocate %d byte buffer for reading file\r\n",
 
279
                (int) in_buf->length);
 
280
        exit(1);
 
281
    }
 
282
 
 
283
    /* this code used to check for incomplete reads, but you can't get
 
284
       an incomplete read on any file for which fstat() is meaningful */
 
285
 
 
286
    count = read(fd, in_buf->value, in_buf->length);
 
287
    if (count < 0) {
 
288
        perror("read");
 
289
        exit(1);
 
290
    }
 
291
    if (count < in_buf->length)
 
292
        printf("Warning, only read in %d bytes, expected %d\r\n",
 
293
                count, (int) in_buf->length);
 
294
}
 
295
 
 
296
/*
 
297
 * Function: call_server
 
298
 *
 
299
 * Purpose: Call the "sign" service.
 
300
 *
 
301
 * Arguments:
 
302
 *
 
303
 *      host            (r) the host providing the service
 
304
 *      port            (r) the port to connect to on host
 
305
 *      service_name    (r) the GSS-API service name to authenticate to
 
306
 *      gss_flags       (r) GSS-API delegation flag (if any)
 
307
 *      auth_flag       (r) whether to do authentication
 
308
 *      wrap_flag       (r) whether to do message wrapping at all
 
309
 *      encrypt_flag    (r) whether to do encryption while wrapping
 
310
 *      mic_flag        (r) whether to request a MIC from the server
 
311
 *      msg             (r) the message to have "signed"
 
312
 *      use_file        (r) whether to treat msg as an input file name
 
313
 *      mcount          (r) the number of times to send the message
 
314
 *
 
315
 * Returns: 0 on success, -1 on failure
 
316
 *
 
317
 * Effects:
 
318
 * 
 
319
 * call_server opens a TCP connection to <host:port> and establishes a
 
320
 * GSS-API context with service_name over the connection.  It then
 
321
 * seals msg in a GSS-API token with gss_wrap, sends it to the server,
 
322
 * reads back a GSS-API signature block for msg from the server, and
 
323
 * verifies it with gss_verify.  -1 is returned if any step fails,
 
324
 * otherwise 0 is returned.  */
 
325
int call_server(char *host, u_short port, gss_OID oid, char *service_name, 
 
326
                OM_uint32 gss_flags, int auth_flag,
 
327
                        int wrap_flag, int encrypt_flag, int mic_flag, int v1_format, 
 
328
                char *msg, int use_file, int mcount)
 
329
{
 
330
     gss_ctx_id_t context;
 
331
     gss_buffer_desc in_buf, out_buf;
 
332
     int s, state;
 
333
     OM_uint32 ret_flags;
 
334
     OM_uint32 maj_stat, min_stat;
 
335
     gss_name_t         src_name, targ_name;
 
336
     gss_buffer_desc    sname, tname;
 
337
     OM_uint32          lifetime;
 
338
     gss_OID            mechanism, name_type;
 
339
     int                is_local;
 
340
     OM_uint32          context_flags;
 
341
     int                is_open;
 
342
     gss_qop_t          qop_state;
 
343
     gss_OID_set        mech_names;
 
344
     gss_buffer_desc    oid_name;
 
345
     size_t     i;
 
346
     int token_flags;
 
347
 
 
348
     /* Open connection */
 
349
     if ((s = connect_to_server(host, port)) < 0)
 
350
          return -1;
 
351
 
 
352
     /* Establish context */
 
353
     if (client_establish_context(s, service_name, gss_flags, auth_flag,
 
354
                                  v1_format, oid, &context,
 
355
                                  &ret_flags) < 0) {
 
356
          (void) closesocket(s);
 
357
          return -1;
 
358
     }
 
359
 
 
360
     if (auth_flag) {
 
361
         if (verbose) {
 
362
             /* display the flags */
 
363
             /* display_ctx_flags(ret_flags); */
 
364
 
 
365
             /* Get context information */
 
366
             maj_stat = gss_inquire_context(&min_stat, context,
 
367
                                        &src_name, &targ_name, &lifetime,
 
368
                                        &mechanism, &context_flags,
 
369
                                        &is_local,
 
370
                                        &is_open);
 
371
             if (maj_stat != GSS_S_COMPLETE) {
 
372
                 display_status("inquiring context", maj_stat, min_stat);
 
373
                 return -1;
 
374
             }
 
375
 
 
376
             maj_stat = gss_display_name(&min_stat, src_name, &sname,
 
377
                                          &name_type);
 
378
             if (maj_stat != GSS_S_COMPLETE) {
 
379
                 display_status("displaying source name", maj_stat, min_stat);
 
380
                 return -1;
 
381
             }
 
382
             maj_stat = gss_display_name(&min_stat, targ_name, &tname,
 
383
                                          (gss_OID *) NULL);
 
384
             if (maj_stat != GSS_S_COMPLETE) {
 
385
                 display_status("displaying target name", maj_stat, min_stat);
 
386
                 return -1;
 
387
             }
 
388
             printf("\"%.*s\" to \"%.*s\", lifetime %d, flags %x, %s, %s\r\n",
 
389
                     (int) sname.length, (char *) sname.value,
 
390
                     (int) tname.length, (char *) tname.value, lifetime,
 
391
                     context_flags,
 
392
                     (is_local) ? "locally initiated" : "remotely initiated",
 
393
                     (is_open) ? "open" : "closed");
 
394
 
 
395
             (void) gss_release_name(&min_stat, &src_name);
 
396
             (void) gss_release_name(&min_stat, &targ_name);
 
397
             (void) gss_release_buffer(&min_stat, &sname);
 
398
             (void) gss_release_buffer(&min_stat, &tname);
 
399
 
 
400
             maj_stat = gss_oid_to_str(&min_stat,
 
401
                                        name_type,
 
402
                                        &oid_name);
 
403
             if (maj_stat != GSS_S_COMPLETE) {
 
404
                 display_status("converting oid->string", maj_stat, min_stat);
 
405
                 return -1;
 
406
             }
 
407
             printf("Name type of source name is %.*s.\r\n",
 
408
                     (int) oid_name.length, (char *) oid_name.value);
 
409
             (void) gss_release_buffer(&min_stat, &oid_name);
 
410
 
 
411
             /* Now get the names supported by the mechanism */
 
412
             maj_stat = gss_inquire_names_for_mech(&min_stat,
 
413
                                                    mechanism,
 
414
                                                    &mech_names);
 
415
             if (maj_stat != GSS_S_COMPLETE) {
 
416
                 display_status("inquiring mech names", maj_stat, min_stat);
 
417
                 return -1;
 
418
             }
 
419
 
 
420
             maj_stat = gss_oid_to_str(&min_stat,
 
421
                                        mechanism,
 
422
                                        &oid_name);
 
423
             if (maj_stat != GSS_S_COMPLETE) {
 
424
                 display_status("converting oid->string", maj_stat, min_stat);
 
425
                 return -1;
 
426
             }
 
427
             printf("Mechanism %.*s supports %d names\r\n",
 
428
                     (int) oid_name.length, (char *) oid_name.value,
 
429
                     (int) mech_names->count);
 
430
             (void) gss_release_buffer(&min_stat, &oid_name);
 
431
 
 
432
             for (i=0; i<mech_names->count; i++) {
 
433
                 maj_stat = gss_oid_to_str(&min_stat,
 
434
                                            &mech_names->elements[i],
 
435
                                            &oid_name);
 
436
                 if (maj_stat != GSS_S_COMPLETE) {
 
437
                     display_status("converting oid->string", maj_stat, min_stat);
 
438
                     return -1;
 
439
                 }
 
440
                 printf("  %d: %.*s\r\n", (int) i,
 
441
                         (int) oid_name.length, (char *) oid_name.value);
 
442
 
 
443
                 (void) gss_release_buffer(&min_stat, &oid_name);
 
444
             }
 
445
             (void) gss_release_oid_set(&min_stat, &mech_names);
 
446
         }
 
447
     }
 
448
     
 
449
     if (use_file) {
 
450
         read_file(msg, &in_buf);
 
451
     } else {
 
452
         /* Seal the message */
 
453
         in_buf.value = msg;
 
454
         in_buf.length = strlen(msg);
 
455
     }
 
456
 
 
457
     for (i = 0; i < mcount; i++) {
 
458
       if (wrap_flag) {
 
459
         maj_stat = gss_wrap(&min_stat, context, encrypt_flag, GSS_C_QOP_DEFAULT,
 
460
                             &in_buf, &state, &out_buf);
 
461
         if (maj_stat != GSS_S_COMPLETE) {
 
462
           display_status("wrapping message", maj_stat, min_stat);
 
463
           (void) closesocket(s);
 
464
           (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
 
465
           return -1;
 
466
         } else if (encrypt_flag && ! state) {
 
467
           fprintf(stderr, "Warning!  Message not encrypted.\r\n");
 
468
         }
 
469
       }
 
470
       else {
 
471
         out_buf = in_buf;
 
472
       }
 
473
 
 
474
       /* Send to server */
 
475
       if (send_token(s, (v1_format?0
 
476
                          :(TOKEN_DATA |
 
477
                          (wrap_flag ? TOKEN_WRAPPED : 0) |
 
478
                          (encrypt_flag ? TOKEN_ENCRYPTED : 0) |
 
479
                          (mic_flag ? TOKEN_SEND_MIC : 0))), &out_buf) < 0) {
 
480
         (void) closesocket(s);
 
481
         (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
 
482
         return -1;
 
483
       }
 
484
       if (out_buf.value != in_buf.value)
 
485
         (void) gss_release_buffer(&min_stat, &out_buf);
 
486
 
 
487
       /* Read signature block into out_buf */
 
488
       if (recv_token(s, &token_flags, &out_buf) < 0) {
 
489
         (void) closesocket(s);
 
490
         (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
 
491
         return -1;
 
492
       }
 
493
 
 
494
       if (mic_flag) {
 
495
         /* Verify signature block */
 
496
         maj_stat = gss_verify_mic(&min_stat, context, &in_buf,
 
497
                                   &out_buf, &qop_state);
 
498
         if (maj_stat != GSS_S_COMPLETE) {
 
499
           display_status("verifying signature", maj_stat, min_stat);
 
500
           (void) closesocket(s);
 
501
           (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
 
502
           return -1;
 
503
         }
 
504
 
 
505
         if (verbose)
 
506
           printf("Signature verified.\r\n");
 
507
       }
 
508
       else {
 
509
         if (verbose)
 
510
           printf("Response received.\r\n");
 
511
       }
 
512
 
 
513
       free (out_buf.value);
 
514
     }
 
515
 
 
516
     if (use_file)
 
517
       free(in_buf.value);
 
518
 
 
519
     /* Send NOOP */
 
520
     if (!v1_format)
 
521
     (void) send_token(s, TOKEN_NOOP, empty_token);
 
522
 
 
523
     if (auth_flag) {
 
524
       /* Delete context */
 
525
       maj_stat = gss_delete_sec_context(&min_stat, &context, &out_buf);
 
526
       if (maj_stat != GSS_S_COMPLETE) {
 
527
         display_status("deleting context", maj_stat, min_stat);
 
528
         (void) closesocket(s);
 
529
         (void) gss_delete_sec_context(&min_stat, &context, GSS_C_NO_BUFFER);
 
530
         return -1;
 
531
       }
 
532
 
 
533
       (void) gss_release_buffer(&min_stat, &out_buf);
 
534
     }
 
535
 
 
536
     (void) closesocket(s);
 
537
     return 0;
 
538
}
 
539
 
 
540
static void parse_oid(char *mechanism, gss_OID *oid)
 
541
{
 
542
    char        *mechstr = 0, *cp;
 
543
    gss_buffer_desc tok;
 
544
    OM_uint32 maj_stat, min_stat;
 
545
    
 
546
    if (isdigit((int) mechanism[0])) {
 
547
        mechstr = malloc(strlen(mechanism)+5);
 
548
        if (!mechstr) {
 
549
            printf("Couldn't allocate mechanism scratch!\r\n");
 
550
            return;
 
551
        }
 
552
        sprintf(mechstr, "{ %s }", mechanism);
 
553
        for (cp = mechstr; *cp; cp++)
 
554
            if (*cp == '.')
 
555
                *cp = ' ';
 
556
        tok.value = mechstr;
 
557
    } else
 
558
        tok.value = mechanism;
 
559
    tok.length = strlen(tok.value);
 
560
    maj_stat = gss_str_to_oid(&min_stat, &tok, oid);
 
561
    if (maj_stat != GSS_S_COMPLETE) {
 
562
        display_status("str_to_oid", maj_stat, min_stat);
 
563
        return;
 
564
    }
 
565
    if (mechstr)
 
566
        free(mechstr);
 
567
}
 
568
 
 
569
int
 
570
gss (char *server_host, char *service_name, char *mechanism, char *msg, int port,
 
571
     int verbose, int delegate, int mutual, int replay, int sequence, 
 
572
     int v1_format, int auth_flag, int wrap_flag,
 
573
     int encrypt_flag, int mic_flag, int ccount, int mcount, char *ccache)
 
574
{
 
575
    int use_file = 0;
 
576
    OM_uint32 gss_flags = 0, min_stat;
 
577
    gss_OID oid = GSS_C_NULL_OID;
 
578
    OM_uint32     minor_status;
 
579
    int i;
 
580
    int rc = 0;
 
581
 
 
582
    if (ccount <= 0)  ccount = 1;
 
583
    if (mcount <= 0)  mcount = 1;
 
584
 
 
585
    if (mechanism && mechanism[0])
 
586
        parse_oid(mechanism, &oid);
 
587
 
 
588
    if ( delegate )
 
589
        gss_flags |= GSS_C_DELEG_FLAG;
 
590
    if ( mutual )
 
591
        gss_flags |= GSS_C_MUTUAL_FLAG;
 
592
    if ( replay )
 
593
        gss_flags |= GSS_C_REPLAY_FLAG;
 
594
    if ( sequence )
 
595
        gss_flags |= GSS_C_SEQUENCE_FLAG;
 
596
 
 
597
    /* By using this function the independence between the application and
 
598
     * the underlying authentication system is broken
 
599
     */
 
600
    if ( ccache && ccache[0] )
 
601
        gss_krb5_ccache_name(&minor_status, ccache, NULL);
 
602
 
 
603
    for (i = 0; i < ccount; i++) {
 
604
        if (call_server(server_host, port, oid, service_name,
 
605
                         gss_flags, auth_flag, wrap_flag, encrypt_flag, mic_flag,
 
606
                         v1_format, msg, use_file, mcount) < 0)
 
607
            rc = -1;
 
608
        break;
 
609
    }
 
610
 
 
611
    if (oid != GSS_C_NULL_OID)
 
612
        (void) gss_release_oid(&min_stat, &oid);
 
613
         
 
614
    return rc;
 
615
}