~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to imap/src/osdep/nt/kerb_w2k.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ========================================================================
 
2
 * Copyright 1988-2006 University of Washington
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * 
 
11
 * ========================================================================
 
12
 */
 
13
 
 
14
/*
 
15
 * Program:     GSSAPI Kerberos Shim 5 for Windows 2000/XP IMAP Toolkit
 
16
 *
 
17
 * Author:      Mark Crispin
 
18
 *              Networks and Distributed Computing
 
19
 *              Computing & Communications
 
20
 *              University of Washington
 
21
 *              Administration Building, AG-44
 
22
 *              Seattle, WA  98195
 
23
 *              Internet: MRC@CAC.Washington.EDU
 
24
 *
 
25
 * Date:        6 March 2000
 
26
 * Last Edited: 30 August 2006
 
27
 */
 
28
 
 
29
/*  The purpose of this module is to be a shim, so that the auth_gss.c module
 
30
 * (written for MIT Kerberos) will compile, link, and run with SSPI Kerberos
 
31
 * on Windows 2000 systems.
 
32
 *  There is no attempt whatsoever to make this be a complete implementation
 
33
 * of GSSAPI.  A number of shortcuts were taken that a real GSSAPI
 
34
 * implementation for SSPI can't do.
 
35
 *  Nor is there any attempt to make the types identical with MIT Kerberos;
 
36
 * you can't link this library with object files compiled with the MIT
 
37
 * Kerberos .h files.
 
38
 */
 
39
 
 
40
 
 
41
/* GSSAPI generic definitions */
 
42
 
 
43
 
 
44
#define SECURITY_WIN32
 
45
#include <security.h>
 
46
 
 
47
 
 
48
/* GSSAPI types for which we use SSPI equivalent types */
 
49
 
 
50
typedef ULONG OM_uint32;
 
51
typedef PCredHandle gss_cred_id_t;
 
52
typedef ULONG gss_cred_usage_t;
 
53
typedef PCtxtHandle gss_ctx_id_t;
 
54
typedef SEC_CHAR * gss_name_t;
 
55
typedef ULONG gss_qop_t;
 
56
 
 
57
 
 
58
/* Major status codes */
 
59
 
 
60
#define GSS_S_COMPLETE SEC_E_OK
 
61
#define GSS_S_BAD_MECH SEC_E_SECPKG_NOT_FOUND
 
62
#define GSS_S_CONTINUE_NEEDED SEC_I_CONTINUE_NEEDED
 
63
#define GSS_S_CREDENTIALS_EXPIRED SEC_E_CERT_EXPIRED
 
64
#define GSS_S_FAILURE SEC_E_INTERNAL_ERROR
 
65
#define GSS_S_NO_CRED SEC_E_NO_CREDENTIALS
 
66
#define GSS_S_NO_CONTEXT SEC_E_INVALID_HANDLE
 
67
 
 
68
 
 
69
/* Flag bits for context-level services */
 
70
 
 
71
#define GSS_C_DELEG_FLAG ISC_REQ_DELEGATE
 
72
#define GSS_C_MUTUAL_FLAG ISC_REQ_MUTUAL_AUTH
 
73
#define GSS_C_REPLAY_FLAG ISC_REQ_REPLAY_DETECT
 
74
#define GSS_C_SEQUENCE_FLAG ISC_REQ_SEQUENCE_DETECT
 
75
#define GSS_C_CONF_FLAG ISC_REQ_CONFIDENTIALITY
 
76
#define GSS_C_INTEG_FLAG ISC_REQ_INTEGRITY
 
77
 
 
78
 
 
79
/* Credential usage options */
 
80
 
 
81
#define GSS_C_BOTH SECPKG_CRED_BOTH
 
82
#define GSS_C_INITIATE SECPKG_CRED_OUTBOUND
 
83
#define GSS_C_ACCEPT SECPKG_CRED_INBOUND
 
84
 
 
85
 
 
86
/* Major status codes defined by shim */
 
87
 
 
88
#define GSS_S_BAD_BINDINGS 100
 
89
#define GSS_S_BAD_NAME 101
 
90
#define GSS_S_BAD_NAMETYPE 102
 
91
#define GSS_S_BAD_STATUS 103
 
92
 
 
93
/* GSSAPI types as used in GSSAPI */
 
94
 
 
95
 
 
96
/* Buffer */
 
97
 
 
98
typedef struct gss_buffer_desc_struct {
 
99
  size_t length;
 
100
  void *value;
 
101
} gss_buffer_desc,*gss_buffer_t;
 
102
 
 
103
 
 
104
/* Object identifier */
 
105
 
 
106
typedef struct gss_OID_desc_struct {
 
107
  OM_uint32 length;
 
108
  void *elements;
 
109
} gss_OID_desc,*gss_OID;
 
110
 
 
111
typedef struct gss_OID_set_desc_struct {
 
112
  size_t count;
 
113
  gss_OID elements;
 
114
} gss_OID_set_desc,*gss_OID_set;
 
115
 
 
116
 
 
117
/* Unused, but needed in prototypes */
 
118
 
 
119
typedef void * gss_channel_bindings_t;
 
120
 
 
121
 
 
122
/* Default constants */
 
123
 
 
124
#define GSS_C_EMPTY_BUFFER {0,NIL}
 
125
#define GSS_C_NO_BUFFER ((gss_buffer_t) NIL)
 
126
#define GSS_C_NO_OID ((gss_OID) NIL)
 
127
#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) NIL)
 
128
#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) NIL)
 
129
#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) NIL)
 
130
#define GSS_C_QOP_DEFAULT NIL
 
131
 
 
132
 
 
133
/* Status code types for gss_display_status */
 
134
 
 
135
#define GSS_C_GSS_CODE 1
 
136
#define GSS_C_MECH_CODE 2
 
137
 
 
138
 
 
139
/* GSSAPI constants */
 
140
 
 
141
const gss_OID gss_nt_service_name;
 
142
#define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
 
143
const gss_OID gss_mech_krb5;
 
144
const gss_OID_set gss_mech_set_krb5;
 
145
 
 
146
/* GSSAPI prototypes */
 
147
 
 
148
 
 
149
OM_uint32 gss_accept_sec_context (OM_uint32 *minor_status,
 
150
                                  gss_ctx_id_t *context_handle,
 
151
                                  gss_cred_id_t acceptor_cred_handle,
 
152
                                  gss_buffer_t input_token_buffer,
 
153
                                  gss_channel_bindings_t input_chan_bindings,
 
154
                                  gss_name_t *src_name,gss_OID *mech_type,
 
155
                                  gss_buffer_t output_token,
 
156
                                  OM_uint32 *ret_flags,OM_uint32 *time_rec,
 
157
                                  gss_cred_id_t *delegated_cred_handle);
 
158
OM_uint32 gss_acquire_cred (OM_uint32 *minor_status,gss_name_t desired_name,
 
159
                            OM_uint32 time_req,gss_OID_set desired_mechs,
 
160
                            gss_cred_usage_t cred_usage,
 
161
                            gss_cred_id_t *output_cred_handle,
 
162
                            gss_OID_set *actual_mechs,OM_uint32 *time_rec);
 
163
OM_uint32 gss_delete_sec_context (OM_uint32 *minor_status,
 
164
                                  gss_ctx_id_t *context_handle,
 
165
                                  gss_buffer_t output_token);
 
166
OM_uint32 gss_display_name (OM_uint32 *minor_status,gss_name_t input_name,
 
167
                            gss_buffer_t output_name_buffer,
 
168
                            gss_OID *output_name_type);
 
169
OM_uint32 gss_display_status (OM_uint32 *minor_status,OM_uint32 status_value,
 
170
                              int status_type,gss_OID mech_type,
 
171
                              OM_uint32 *message_context,
 
172
                              gss_buffer_t status_string);
 
173
OM_uint32 gss_import_name (OM_uint32 *minor_status,
 
174
                           gss_buffer_t input_name_buffer,
 
175
                           gss_OID input_name_type,gss_name_t *output_name);
 
176
OM_uint32 gss_init_sec_context (OM_uint32 *minor_status,
 
177
                                gss_cred_id_t claimant_cred_handle,
 
178
                                gss_ctx_id_t *context_handle,
 
179
                                gss_name_t target_name,gss_OID mech_type,
 
180
                                OM_uint32 req_flags,OM_uint32 time_req,
 
181
                                gss_channel_bindings_t input_chan_bindings,
 
182
                                gss_buffer_t input_token,
 
183
                                gss_OID *actual_mech_type,
 
184
                                gss_buffer_t output_token,OM_uint32 *ret_flags,
 
185
                                OM_uint32 *time_rec);
 
186
OM_uint32 gss_release_buffer (OM_uint32 *minor_status,gss_buffer_t buffer);
 
187
OM_uint32 gss_release_cred (OM_uint32 *minor_status,gss_cred_id_t *cred_handle);
 
188
OM_uint32 gss_release_name (OM_uint32 *minor_status,gss_name_t *input_name);
 
189
OM_uint32 gss_wrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
 
190
                    int conf_req_flag,gss_qop_t qop_req,
 
191
                    gss_buffer_t input_message_buffer,int *conf_state,
 
192
                    gss_buffer_t output_message_buffer);
 
193
OM_uint32 gss_unwrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
 
194
                      gss_buffer_t input_message_buffer,
 
195
                      gss_buffer_t output_message_buffer,int *conf_state,
 
196
                      gss_qop_t *qop_state);
 
197
 
 
198
/* Kerberos definitions */
 
199
 
 
200
long kerberos_server_valid (void);
 
201
long kerberos_try_kinit (OM_uint32 error);
 
202
char *kerberos_login (char *user,char *authuser,int argc,char *argv[]);
 
203
 
 
204
 
 
205
#define STRING WINSTRING        /* conflict with mail.h */
 
206
#include <NTSecAPI.h>
 
207
 
 
208
/* GSSAPI build-in object identifiers */
 
209
 
 
210
static gss_OID_desc oids[] = {  /* stupid C language makes this necessary */
 
211
  {10,"\052\206\110\206\367\022\001\002\001\004"},
 
212
  {9,"\052\206\110\206\367\022\001\002\002"}
 
213
};
 
214
 
 
215
                                /* stupid C language ditto */
 
216
static gss_OID_set_desc oidsets[] = {
 
217
  {1,(gss_OID) oids+1}
 
218
};
 
219
 
 
220
                                /* these are the real OIDs */
 
221
const gss_OID gss_nt_service_name = oids+0;
 
222
const gss_OID gss_mech_krb5 = oids+1;
 
223
const gss_OID_set gss_mech_set_krb5 = oidsets+0;
 
224
 
 
225
 
 
226
/* Other globals */
 
227
 
 
228
                                /* substitute for GSS_C_NO_CREDENTIAL */
 
229
static gss_cred_id_t gss_default_cred = NIL;
 
230
 
 
231
/* GSSAPI import name (convert to full service principal name)
 
232
 * Accepts: pointer to return minor status
 
233
 *          buffer containining input name
 
234
 *          type of input name
 
235
 *          pointer to return output internal name
 
236
 * Returns: major status, always
 
237
 */
 
238
 
 
239
OM_uint32 gss_import_name (OM_uint32 *minor_status,
 
240
                           gss_buffer_t input_name_buffer,
 
241
                           gss_OID input_name_type,gss_name_t *output_name)
 
242
{
 
243
  OM_uint32 major_status = GSS_S_COMPLETE;
 
244
  TimeStamp expiry;
 
245
  static CredHandle gss_cred;
 
246
  char *s,tmp[MAILTMPLEN];
 
247
  *minor_status = 0;            /* never any minor status */
 
248
  if (!gss_default_cred) {      /* default credentials set up yet? */
 
249
    if (AcquireCredentialsHandle/* no, acquire them now */
 
250
        (NIL,MICROSOFT_KERBEROS_NAME_A,SECPKG_CRED_OUTBOUND,NIL,NIL,NIL,NIL,
 
251
         &gss_cred,&expiry) != SEC_E_OK) return GSS_S_FAILURE;
 
252
                                /* have default credentials now */
 
253
    gss_default_cred = &gss_cred;
 
254
  }
 
255
                                /* must be the gss_nt_service_name format */
 
256
  if (input_name_type != gss_nt_service_name)
 
257
    major_status = GSS_S_BAD_NAMETYPE;
 
258
                                /* name must be of sane length */
 
259
  else if (input_name_buffer->length > (MAILTMPLEN/2))
 
260
    major_status = GSS_S_BAD_NAME;
 
261
  else {                        /* copy name */
 
262
    memcpy (tmp,input_name_buffer->value,input_name_buffer->length);
 
263
    tmp[input_name_buffer->length] = '\0';
 
264
    if (s = strchr (tmp,'@')) { /* find service/host/delimiter */
 
265
      *s = '/';                 /* convert to full service principal name */
 
266
      *output_name = cpystr (tmp);
 
267
    }
 
268
    else major_status = GSS_S_BAD_NAME;
 
269
  }
 
270
  return major_status;
 
271
}
 
272
 
 
273
/* GSSAPI Initialize security context
 
274
 * Accepts: pointer to return minor status
 
275
 *          claimant credential handle
 
276
 *          context (NIL means "none assigned yet")
 
277
 *          desired principal
 
278
 *          desired mechanisms
 
279
 *          required context attributes
 
280
 *          desired lifetime
 
281
 *          input channel bindings
 
282
 *          input token buffer
 
283
 *          pointer to return mechanism type
 
284
 *          buffer to return output token
 
285
 *          pointer to return flags
 
286
 *          pointer to return context lifetime
 
287
 * Returns: major status, always
 
288
 */
 
289
 
 
290
OM_uint32 gss_init_sec_context (OM_uint32 *minor_status,
 
291
                                gss_cred_id_t claimant_cred_handle,
 
292
                                gss_ctx_id_t *context_handle,
 
293
                                gss_name_t target_name,gss_OID mech_type,
 
294
                                OM_uint32 req_flags,OM_uint32 time_req,
 
295
                                gss_channel_bindings_t input_chan_bindings,
 
296
                                gss_buffer_t input_token,
 
297
                                gss_OID *actual_mech_type,
 
298
                                gss_buffer_t output_token,OM_uint32 *ret_flags,
 
299
                                OM_uint32 *time_rec)
 
300
{
 
301
  OM_uint32 i;
 
302
  OM_uint32 major_status;
 
303
  TimeStamp expiry;
 
304
  SecBuffer ibuf[1],obuf[1];
 
305
  SecBufferDesc ibufs,obufs;
 
306
  *minor_status = 0;            /* never any minor status */
 
307
                                /* error if non-default time requested */
 
308
  if (time_req) return GSS_S_FAILURE;
 
309
  if (mech_type && memcmp (mech_type,gss_mech_krb5,sizeof (gss_OID)))
 
310
    return GSS_S_BAD_MECH;
 
311
                                /* ditto if any channel bindings */
 
312
  if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS)
 
313
    return GSS_S_BAD_BINDINGS;
 
314
 
 
315
                                /* apply default credential if necessary */
 
316
  if (claimant_cred_handle == GSS_C_NO_CREDENTIAL)
 
317
    claimant_cred_handle = gss_default_cred;
 
318
                                /* create output buffer storage as needed */
 
319
  req_flags |= ISC_REQ_ALLOCATE_MEMORY;
 
320
                                /* make output buffer */
 
321
  obuf[0].BufferType = SECBUFFER_TOKEN;
 
322
  obuf[0].cbBuffer = 0; obuf[0].pvBuffer = NIL;
 
323
                                /* output buffer descriptor */
 
324
  obufs.ulVersion = SECBUFFER_VERSION;
 
325
  obufs.cBuffers = 1;
 
326
  obufs.pBuffers = obuf;
 
327
                                /* first time caller? */
 
328
  if (*context_handle == GSS_C_NO_CONTEXT) {
 
329
                                /* yes, set up output context handle */
 
330
    PCtxtHandle ctx = (PCtxtHandle) fs_get (sizeof (CtxtHandle));
 
331
    major_status = InitializeSecurityContext (claimant_cred_handle,NIL,
 
332
                                              target_name,req_flags,0,
 
333
                                              SECURITY_NETWORK_DREP,NIL,0,ctx,
 
334
                                              &obufs,
 
335
                                              ret_flags ? ret_flags : &i,
 
336
                                              &expiry);
 
337
    *context_handle = ctx;      /* return updated context */
 
338
  }
 
339
  else {                        /* no, make SSPI buffer from GSSAPI buffer */
 
340
    ibuf[0].BufferType = obuf[0].BufferType = SECBUFFER_TOKEN;
 
341
    ibuf[0].cbBuffer = input_token->length;
 
342
    ibuf[0].pvBuffer = input_token->value;
 
343
                                /* input buffer descriptor */
 
344
    ibufs.ulVersion = SECBUFFER_VERSION;
 
345
    ibufs.cBuffers = 1;
 
346
    ibufs.pBuffers = ibuf;
 
347
    major_status = InitializeSecurityContext (claimant_cred_handle,
 
348
                                              *context_handle,target_name,
 
349
                                              req_flags,0,
 
350
                                              SECURITY_NETWORK_DREP,&ibufs,0,
 
351
                                              *context_handle,&obufs,
 
352
                                              ret_flags ? ret_flags : &i,
 
353
                                              &expiry);
 
354
  }
 
355
                                /* return output */
 
356
  output_token->value = obuf[0].pvBuffer;
 
357
  output_token->length = obuf[0].cbBuffer;
 
358
                                /* in case client wanted lifetime returned */
 
359
  if (time_rec) *time_rec = expiry.LowPart;
 
360
  return major_status;
 
361
}
 
362
 
 
363
/* GSSAPI display status text
 
364
 * Accepts: pointer to return minor status
 
365
 *          status to display
 
366
 *          status type
 
367
 *          message context for continuation
 
368
 *          buffer to write status string
 
369
 * Returns: major status, always
 
370
 */
 
371
 
 
372
OM_uint32 gss_display_status (OM_uint32 *minor_status,OM_uint32 status_value,
 
373
                              int status_type,gss_OID mech_type,
 
374
                              OM_uint32 *message_context,
 
375
                              gss_buffer_t status_string)
 
376
{
 
377
  char *s,tmp[MAILTMPLEN];
 
378
  *minor_status = 0;            /* never any minor status */
 
379
  if (*message_context) return GSS_S_FAILURE;
 
380
  switch (status_type) {        /* what type of status code? */
 
381
  case GSS_C_GSS_CODE:          /* major_status */
 
382
    switch (status_value) {     /* analyze status value */
 
383
    case GSS_S_FAILURE:
 
384
      s = "Unspecified failure"; break;
 
385
    case GSS_S_CREDENTIALS_EXPIRED:
 
386
      s = "Credentials expired"; break;
 
387
    case GSS_S_BAD_BINDINGS:
 
388
      s = "Bad bindings"; break;
 
389
    case GSS_S_BAD_MECH:
 
390
      s = "Bad mechanism type"; break;
 
391
    case GSS_S_BAD_NAME:
 
392
      s = "Bad name"; break;
 
393
    case GSS_S_BAD_NAMETYPE:
 
394
      s = "Bad name type"; break;
 
395
    case GSS_S_BAD_STATUS:
 
396
      s = "Bad status"; break;
 
397
    case GSS_S_NO_CONTEXT:
 
398
      s = "Invalid context handle"; break;
 
399
    case GSS_S_NO_CRED:
 
400
      s = "Unable to authenticate to Kerberos service";
 
401
      mail_parameters (NIL,DISABLE_AUTHENTICATOR,"GSSAPI");
 
402
      break;
 
403
    case SEC_E_NO_AUTHENTICATING_AUTHORITY:
 
404
      s = "No authenticating authority"; break;
 
405
    case SEC_E_TARGET_UNKNOWN:
 
406
      s = "Destination server unknown to Kerberos service"; break;
 
407
    default:
 
408
      sprintf (s = tmp,"SSPI code %lx",status_value);
 
409
    }
 
410
    break;
 
411
  case GSS_C_MECH_CODE:         /* minor status - drop into default */
 
412
  default:
 
413
    return GSS_S_BAD_STATUS;    /* bad status type */
 
414
  }
 
415
                                /* return status string */
 
416
  status_string->length = strlen (status_string->value = cpystr (s));
 
417
  return GSS_S_COMPLETE;
 
418
}
 
419
 
 
420
/* GSSAPI delete security context
 
421
 * Accepts: pointer to return minor status
 
422
 *          context to delete
 
423
 *          output context token
 
424
 * Returns: major status, always
 
425
 */
 
426
 
 
427
OM_uint32 gss_delete_sec_context (OM_uint32 *minor_status,
 
428
                                  gss_ctx_id_t *context_handle,
 
429
                                  gss_buffer_t output_token)
 
430
{
 
431
  OM_uint32 major_status;
 
432
  *minor_status = 0;            /* never any minor status */
 
433
                                /* output token not supported */
 
434
  major_status = output_token ? GSS_S_FAILURE :
 
435
    DeleteSecurityContext (*context_handle);
 
436
  fs_give ((void **) context_handle);
 
437
  return major_status;
 
438
}
 
439
 
 
440
 
 
441
/* GSSAPI release buffer
 
442
 * Accepts: pointer to return minor status
 
443
 *          buffer to release
 
444
 * Returns: GSS_S_COMPLETE, always
 
445
 */
 
446
 
 
447
OM_uint32 gss_release_buffer (OM_uint32 *minor_status,gss_buffer_t buffer)
 
448
{
 
449
  *minor_status = 0;            /* never any minor status */
 
450
  fs_give (&buffer->value);
 
451
  return GSS_S_COMPLETE;
 
452
}
 
453
 
 
454
 
 
455
/* GSSAPI release name
 
456
 * Accepts: pointer to return minor status
 
457
 *          pointer to name to release
 
458
 * Returns: GSS_S_COMPLETE, always
 
459
 */
 
460
 
 
461
OM_uint32 gss_release_name (OM_uint32 *minor_status,gss_name_t *input_name)
 
462
{
 
463
  *minor_status = 0;            /* never any minor status */
 
464
  fs_give (input_name);
 
465
  return GSS_S_COMPLETE;
 
466
}
 
467
 
 
468
/* GSSAPI wrap data
 
469
 * Accepts: pointer to return minor status
 
470
 *          context handle
 
471
 *          requested confidentiality
 
472
 *          requested quality of protection
 
473
 *          input message buffer
 
474
 *          pointer to return confidentiality state
 
475
 *          output message buffer
 
476
 * Returns: major status, always
 
477
 */
 
478
 
 
479
OM_uint32 gss_wrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
 
480
                    int conf_req_flag,gss_qop_t qop_req,
 
481
                    gss_buffer_t input_message_buffer,int *conf_state,
 
482
                    gss_buffer_t output_message_buffer)
 
483
{
 
484
  OM_uint32 major_status;
 
485
  SecBuffer buf[3];
 
486
  SecBufferDesc bufs;
 
487
  SecPkgContext_Sizes sizes;
 
488
  *minor_status = NIL;          /* never any minor status */
 
489
  *conf_state = conf_req_flag;  /* same as requested */
 
490
  if ((major_status =           /* get trailer and padding sizes */
 
491
       QueryContextAttributes (context_handle,SECPKG_ATTR_SIZES,&sizes)) ==
 
492
      SEC_E_OK) {
 
493
                                /* create big enough output buffer */
 
494
    output_message_buffer->value =
 
495
      fs_get (sizes.cbSecurityTrailer + input_message_buffer->length +
 
496
              sizes.cbBlockSize);
 
497
    /* MSDN claims that for EncryptMessage() in Kerberos, you need an
 
498
     * uninitialized SECBUFFER_STREAM_HEADER; a SECBUFFER_DATA that "contains
 
499
     * the message to be encrypted.  The message is encrypted in place,
 
500
     * overwriting the original contents of its buffer"; an uninitialized
 
501
     * SECBUFFER_STREAM_TRAILER, and an uninitialized SECBUFFER_EMPTY.  I've
 
502
     * never been able to get it to work that way.
 
503
     */
 
504
    bufs.cBuffers = 3;          /* set up buffer descriptor */
 
505
    bufs.pBuffers = buf;
 
506
    bufs.ulVersion = SECBUFFER_VERSION;
 
507
    buf[0].BufferType = SECBUFFER_TOKEN;
 
508
    buf[0].pvBuffer = output_message_buffer->value;
 
509
    buf[0].cbBuffer = sizes.cbSecurityTrailer;
 
510
                                /* I/O buffer */
 
511
    buf[1].BufferType = SECBUFFER_DATA;
 
512
    buf[1].pvBuffer = ((char *) buf[0].pvBuffer) + buf[0].cbBuffer;
 
513
    buf[1].cbBuffer = input_message_buffer->length;
 
514
    memcpy (buf[1].pvBuffer,input_message_buffer->value,buf[1].cbBuffer);
 
515
    buf[2].BufferType = SECBUFFER_PADDING;
 
516
    buf[2].pvBuffer = ((char *) buf[1].pvBuffer) + buf[1].cbBuffer;
 
517
    buf[2].cbBuffer = sizes.cbBlockSize;
 
518
    if ((major_status = EncryptMessage (context_handle,qop_req,&bufs,0)) ==
 
519
        GSS_S_COMPLETE) {
 
520
                                /* slide data as necessary (how annoying!) */
 
521
      unsigned long i = sizes.cbSecurityTrailer - buf[0].cbBuffer;
 
522
      if (i) buf[1].pvBuffer =
 
523
               memmove (((char *) buf[0].pvBuffer) + buf[0].cbBuffer,
 
524
                        buf[1].pvBuffer,buf[1].cbBuffer);
 
525
      if (i += (input_message_buffer->length - buf[1].cbBuffer))
 
526
        buf[1].pvBuffer = memmove (((char *)buf[1].pvBuffer) + buf[1].cbBuffer,
 
527
                   buf[2].pvBuffer,buf[2].cbBuffer);
 
528
      output_message_buffer->length = buf[0].cbBuffer + buf[1].cbBuffer +
 
529
        buf[2].cbBuffer;
 
530
    }
 
531
    else fs_give (&output_message_buffer->value);
 
532
  }
 
533
  return major_status;          /* return status */
 
534
}
 
535
 
 
536
/* GSSAPI unwrap data
 
537
 * Accepts: pointer to return minor status
 
538
 *          context handle
 
539
 *          input message buffer
 
540
 *          output message buffer
 
541
 *          pointer to return confidentiality state
 
542
 *          pointer to return quality of protection
 
543
 * Returns: major status, always
 
544
 */
 
545
 
 
546
OM_uint32 gss_unwrap (OM_uint32 *minor_status,gss_ctx_id_t context_handle,
 
547
                      gss_buffer_t input_message_buffer,
 
548
                      gss_buffer_t output_message_buffer,int *conf_state,
 
549
                      gss_qop_t *qop_state)
 
550
{
 
551
  OM_uint32 major_status;
 
552
  SecBuffer buf[2];
 
553
  SecBufferDesc bufs;
 
554
  *minor_status = NIL;          /* never any minor status */
 
555
  *conf_state = NIL;            /* or confidentiality state */
 
556
  /* MSDN implies that all that is needed for DecryptMessage() in Kerberos
 
557
   * is a single SECBUFFER_DATA which "contains the encrypted message.  The
 
558
   * encrypted message is decrypted in place, overwriting the original
 
559
   * contents of its buffer."  I've never been able to get it to work without
 
560
   * using a SECBUFFER_STREAM for input and an uninitialized SECBUFFER_DATA
 
561
   * for output.
 
562
   * It *does* overwrite the input buffer, but not at the same point; e.g.
 
563
   * with an input pointer of 0xa140a8 and size of 53, the output ends up
 
564
   * at 0xa140d5 and size of 4.
 
565
   */
 
566
  bufs.cBuffers = 2;            /* set up buffer descriptor */
 
567
  bufs.pBuffers = buf;
 
568
  bufs.ulVersion = SECBUFFER_VERSION;
 
569
                                /* input buffer */
 
570
  buf[0].BufferType = SECBUFFER_STREAM;
 
571
  buf[0].pvBuffer = input_message_buffer->value;
 
572
  buf[0].cbBuffer = input_message_buffer->length;
 
573
                                /* output buffer */
 
574
  buf[1].BufferType = SECBUFFER_DATA;
 
575
  buf[1].pvBuffer = NIL;
 
576
  buf[1].cbBuffer = 0;
 
577
                                /* decrypt and copy to output buffer */
 
578
  if ((major_status = DecryptMessage (context_handle,&bufs,0,qop_state)) ==
 
579
      SEC_E_OK)
 
580
   memcpy (output_message_buffer->value = fs_get (buf[1].cbBuffer),
 
581
           buf[1].pvBuffer,output_message_buffer->length = buf[1].cbBuffer);
 
582
  return major_status;          /* return status */
 
583
}
 
584
 
 
585
/* From here on are server-only functions, currently unused */
 
586
 
 
587
 
 
588
/* GSSAPI acquire credentials
 
589
 * Accepts: pointer to return minor status
 
590
 *          desired principal
 
591
 *          desired lifetime
 
592
 *          desired mechanisms
 
593
 *          credentials usage
 
594
 *          pointer to return credentials handle
 
595
 *          pointer to return mechanisms
 
596
 *          pointer to return lifetime
 
597
 * Returns: GSS_S_FAILURE, always
 
598
 */
 
599
 
 
600
OM_uint32 gss_acquire_cred (OM_uint32 *minor_status,gss_name_t desired_name,
 
601
                            OM_uint32 time_req,gss_OID_set desired_mechs,
 
602
                            gss_cred_usage_t cred_usage,
 
603
                            gss_cred_id_t *output_cred_handle,
 
604
                            gss_OID_set *actual_mechs,OM_uint32 *time_rec)
 
605
{
 
606
  *minor_status = 0;            /* never any minor status */
 
607
  return GSS_S_FAILURE;         /* server only */
 
608
}
 
609
 
 
610
 
 
611
/* GSSAPI release credentials
 
612
 * Accepts: pointer to return minor status
 
613
 *          credentials handle to free
 
614
 * Returns: GSS_S_COMPLETE, always
 
615
 */
 
616
 
 
617
OM_uint32 gss_release_cred (OM_uint32 *minor_status,gss_cred_id_t *cred_handle)
 
618
{
 
619
  *minor_status = 0;            /* never any minor status */
 
620
  return GSS_S_FAILURE;         /* server only */
 
621
}
 
622
 
 
623
/* GSSAPI Accept security context
 
624
 * Accepts: pointer to return minor status
 
625
 *          context
 
626
 *          acceptor credentials
 
627
 *          input token buffer
 
628
 *          input channel bindings
 
629
 *          pointer to return source name
 
630
 *          pointer to return mechanism type
 
631
 *          buffer to return output token
 
632
 *          pointer to return flags
 
633
 *          pointer to return context lifetime
 
634
 *          pointer to return delegated credentials
 
635
 * Returns: GSS_S_FAILURE, always
 
636
 */
 
637
 
 
638
OM_uint32 gss_accept_sec_context (OM_uint32 *minor_status,
 
639
                                  gss_ctx_id_t *context_handle,
 
640
                                  gss_cred_id_t acceptor_cred_handle,
 
641
                                  gss_buffer_t input_token_buffer,
 
642
                                  gss_channel_bindings_t input_chan_bindings,
 
643
                                  gss_name_t *src_name,gss_OID *mech_type,
 
644
                                  gss_buffer_t output_token,
 
645
                                  OM_uint32 *ret_flags,OM_uint32 *time_rec,
 
646
                                  gss_cred_id_t *delegated_cred_handle)
 
647
{
 
648
  *minor_status = 0;            /* never any minor status */
 
649
  return GSS_S_FAILURE;         /* server only */
 
650
}
 
651
 
 
652
 
 
653
/* GSSAPI return printable name
 
654
 * Accepts: pointer to return minor status
 
655
 *          internal name
 
656
 *          buffer to return output name
 
657
 *          output name type
 
658
 * Returns: GSS_S_FAILURE, always
 
659
 */
 
660
 
 
661
OM_uint32 gss_display_name (OM_uint32 *minor_status,gss_name_t input_name,
 
662
                            gss_buffer_t output_name_buffer,
 
663
                            gss_OID *output_name_type)
 
664
{
 
665
  *minor_status = 0;            /* never any minor status */
 
666
  return GSS_S_FAILURE;         /* server only */
 
667
}
 
668
 
 
669
/* Kerberos server valid check
 
670
 * Returns: T if have keytab, NIL otherwise
 
671
 */
 
672
 
 
673
long kerberos_server_valid ()
 
674
{
 
675
  return NIL;
 
676
}
 
677
 
 
678
 
 
679
/* Kerberos check for missing or expired credentials
 
680
 * Returns: T if should suggest running kinit, NIL otherwise
 
681
 */
 
682
 
 
683
long kerberos_try_kinit (OM_uint32 error)
 
684
{
 
685
  return NIL;
 
686
}
 
687
 
 
688
/* Kerberos server log in
 
689
 * Accepts: authorization ID as user name
 
690
 *          authentication ID as Kerberos principal
 
691
 *          argument count
 
692
 *          argument vector
 
693
 * Returns: logged in user name if logged in, NIL otherwise
 
694
 */
 
695
 
 
696
char *kerberos_login (char *user,char *authuser,int argc,char *argv[])
 
697
{
 
698
  return NIL;
 
699
}