imapext-2007

annotate src/c-client/auth_gss.c @ 0:ada5e610ab86

imap-2007e
author yuuji@gentei.org
date Mon, 14 Sep 2009 15:17:45 +0900
parents
children
rev   line source
yuuji@0 1 /* ========================================================================
yuuji@0 2 * Copyright 1988-2006 University of Washington
yuuji@0 3 *
yuuji@0 4 * Licensed under the Apache License, Version 2.0 (the "License");
yuuji@0 5 * you may not use this file except in compliance with the License.
yuuji@0 6 * You may obtain a copy of the License at
yuuji@0 7 *
yuuji@0 8 * http://www.apache.org/licenses/LICENSE-2.0
yuuji@0 9 *
yuuji@0 10 *
yuuji@0 11 * ========================================================================
yuuji@0 12 */
yuuji@0 13
yuuji@0 14 /*
yuuji@0 15 * Program: GSSAPI authenticator
yuuji@0 16 *
yuuji@0 17 * Author: Mark Crispin
yuuji@0 18 * Networks and Distributed Computing
yuuji@0 19 * Computing & Communications
yuuji@0 20 * University of Washington
yuuji@0 21 * Administration Building, AG-44
yuuji@0 22 * Seattle, WA 98195
yuuji@0 23 * Internet: MRC@CAC.Washington.EDU
yuuji@0 24 *
yuuji@0 25 * Date: 12 January 1998
yuuji@0 26 * Last Edited: 30 August 2006
yuuji@0 27 */
yuuji@0 28
yuuji@0 29
yuuji@0 30 long auth_gssapi_valid (void);
yuuji@0 31 long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
yuuji@0 32 char *service,NETMBX *mb,void *stream,
yuuji@0 33 unsigned long *trial,char *user);
yuuji@0 34 long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
yuuji@0 35 authrespond_t responder,char *service,NETMBX *mb,
yuuji@0 36 void *stream,char *user,kinit_t ki);
yuuji@0 37 char *auth_gssapi_server (authresponse_t responder,int argc,char *argv[]);
yuuji@0 38
yuuji@0 39
yuuji@0 40 AUTHENTICATOR auth_gss = {
yuuji@0 41 AU_SECURE | AU_AUTHUSER, /* secure authenticator */
yuuji@0 42 "GSSAPI", /* authenticator name */
yuuji@0 43 auth_gssapi_valid, /* check if valid */
yuuji@0 44 auth_gssapi_client, /* client method */
yuuji@0 45 auth_gssapi_server, /* server method */
yuuji@0 46 NIL /* next authenticator */
yuuji@0 47 };
yuuji@0 48
yuuji@0 49 #define AUTH_GSSAPI_P_NONE 1
yuuji@0 50 #define AUTH_GSSAPI_P_INTEGRITY 2
yuuji@0 51 #define AUTH_GSSAPI_P_PRIVACY 4
yuuji@0 52
yuuji@0 53 #define AUTH_GSSAPI_C_MAXSIZE 8192
yuuji@0 54
yuuji@0 55 #define SERVER_LOG(x,y) syslog (LOG_ALERT,x,y)
yuuji@0 56
yuuji@0 57 /* Check if GSSAPI valid on this system
yuuji@0 58 * Returns: T if valid, NIL otherwise
yuuji@0 59 */
yuuji@0 60
yuuji@0 61 long auth_gssapi_valid (void)
yuuji@0 62 {
yuuji@0 63 char tmp[MAILTMPLEN];
yuuji@0 64 OM_uint32 smn;
yuuji@0 65 gss_buffer_desc buf;
yuuji@0 66 gss_name_t name;
yuuji@0 67 /* make service name */
yuuji@0 68 sprintf (tmp,"%s@%s",(char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
yuuji@0 69 mylocalhost ());
yuuji@0 70 buf.length = strlen (buf.value = tmp);
yuuji@0 71 /* see if can build a name */
yuuji@0 72 if (gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&name) !=
yuuji@0 73 GSS_S_COMPLETE) return NIL;
yuuji@0 74 /* remove server method if no keytab */
yuuji@0 75 if (!kerberos_server_valid ()) auth_gss.server = NIL;
yuuji@0 76 gss_release_name (&smn,&name);/* finished with name */
yuuji@0 77 return LONGT;
yuuji@0 78 }
yuuji@0 79
yuuji@0 80 /* Client authenticator
yuuji@0 81 * Accepts: challenger function
yuuji@0 82 * responder function
yuuji@0 83 * SASL service name
yuuji@0 84 * parsed network mailbox structure
yuuji@0 85 * stream argument for functions
yuuji@0 86 * pointer to current trial count
yuuji@0 87 * returned user name
yuuji@0 88 * Returns: T if success, NIL otherwise, number of trials incremented if retry
yuuji@0 89 */
yuuji@0 90
yuuji@0 91 long auth_gssapi_client (authchallenge_t challenger,authrespond_t responder,
yuuji@0 92 char *service,NETMBX *mb,void *stream,
yuuji@0 93 unsigned long *trial,char *user)
yuuji@0 94 {
yuuji@0 95 gss_buffer_desc chal;
yuuji@0 96 kinit_t ki = (kinit_t) mail_parameters (NIL,GET_KINIT,NIL);
yuuji@0 97 long ret = NIL;
yuuji@0 98 *trial = 65535; /* never retry */
yuuji@0 99 /* get initial (empty) challenge */
yuuji@0 100 if (chal.value = (*challenger) (stream,(unsigned long *) &chal.length)) {
yuuji@0 101 if (chal.length) { /* abort if challenge non-empty */
yuuji@0 102 mm_log ("Server bug: non-empty initial GSSAPI challenge",WARN);
yuuji@0 103 (*responder) (stream,NIL,0);
yuuji@0 104 ret = LONGT; /* will get a BAD response back */
yuuji@0 105 }
yuuji@0 106 else if (mb->authuser[0] && strcmp (mb->authuser,myusername ())) {
yuuji@0 107 mm_log ("Can't use Kerberos: invalid /authuser",WARN);
yuuji@0 108 (*responder) (stream,NIL,0);
yuuji@0 109 ret = LONGT; /* will get a BAD response back */
yuuji@0 110 }
yuuji@0 111 else ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
yuuji@0 112 stream,user,ki);
yuuji@0 113 }
yuuji@0 114 return ret;
yuuji@0 115 }
yuuji@0 116
yuuji@0 117 /* Client authenticator worker function
yuuji@0 118 * Accepts: challenger function
yuuji@0 119 * responder function
yuuji@0 120 * SASL service name
yuuji@0 121 * parsed network mailbox structure
yuuji@0 122 * stream argument for functions
yuuji@0 123 * returned user name
yuuji@0 124 * kinit function pointer if should retry with kinit
yuuji@0 125 * Returns: T if success, NIL otherwise
yuuji@0 126 */
yuuji@0 127
yuuji@0 128 long auth_gssapi_client_work (authchallenge_t challenger,gss_buffer_desc chal,
yuuji@0 129 authrespond_t responder,char *service,NETMBX *mb,
yuuji@0 130 void *stream,char *user,kinit_t ki)
yuuji@0 131 {
yuuji@0 132 char tmp[MAILTMPLEN];
yuuji@0 133 OM_uint32 smj,smn,dsmj,dsmn;
yuuji@0 134 OM_uint32 mctx = 0;
yuuji@0 135 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
yuuji@0 136 gss_buffer_desc resp,buf;
yuuji@0 137 long i;
yuuji@0 138 int conf;
yuuji@0 139 gss_qop_t qop;
yuuji@0 140 gss_name_t crname = NIL;
yuuji@0 141 blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL);
yuuji@0 142 void *data;
yuuji@0 143 long ret = NIL;
yuuji@0 144 sprintf (tmp,"%s@%s",service,mb->host);
yuuji@0 145 buf.length = strlen (buf.value = tmp);
yuuji@0 146 /* get service name */
yuuji@0 147 if (gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&crname) !=
yuuji@0 148 GSS_S_COMPLETE) {
yuuji@0 149 mm_log ("Can't import Kerberos service name",WARN);
yuuji@0 150 (*responder) (stream,NIL,0);
yuuji@0 151 }
yuuji@0 152 else {
yuuji@0 153 data = (*bn) (BLOCK_SENSITIVE,NIL);
yuuji@0 154 /* negotiate with KDC */
yuuji@0 155 smj = gss_init_sec_context (&smn,GSS_C_NO_CREDENTIAL,&ctx,crname,NIL,
yuuji@0 156 GSS_C_INTEG_FLAG | GSS_C_MUTUAL_FLAG |
yuuji@0 157 GSS_C_REPLAY_FLAG,0,GSS_C_NO_CHANNEL_BINDINGS,
yuuji@0 158 GSS_C_NO_BUFFER,NIL,&resp,NIL,NIL);
yuuji@0 159 (*bn) (BLOCK_NONSENSITIVE,data);
yuuji@0 160
yuuji@0 161 /* while continuation needed */
yuuji@0 162 while (smj == GSS_S_CONTINUE_NEEDED) {
yuuji@0 163 if (chal.value) fs_give ((void **) &chal.value);
yuuji@0 164 /* send response, get next challenge */
yuuji@0 165 i = (*responder) (stream,resp.value,resp.length) &&
yuuji@0 166 (chal.value = (*challenger) (stream,(unsigned long *) &chal.length));
yuuji@0 167 gss_release_buffer (&smn,&resp);
yuuji@0 168 if (i) { /* negotiate continuation with KDC */
yuuji@0 169 data = (*bn) (BLOCK_SENSITIVE,NIL);
yuuji@0 170 switch (smj = /* make sure continuation going OK */
yuuji@0 171 gss_init_sec_context (&smn,GSS_C_NO_CREDENTIAL,&ctx,
yuuji@0 172 crname,GSS_C_NO_OID,GSS_C_INTEG_FLAG |
yuuji@0 173 GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,0,
yuuji@0 174 GSS_C_NO_CHANNEL_BINDINGS,&chal,NIL,
yuuji@0 175 &resp,NIL,NIL)) {
yuuji@0 176 case GSS_S_CONTINUE_NEEDED:
yuuji@0 177 case GSS_S_COMPLETE:
yuuji@0 178 break;
yuuji@0 179 default: /* error, don't need context any more */
yuuji@0 180 gss_delete_sec_context (&smn,&ctx,NIL);
yuuji@0 181 }
yuuji@0 182 (*bn) (BLOCK_NONSENSITIVE,data);
yuuji@0 183 }
yuuji@0 184 else { /* error in continuation */
yuuji@0 185 mm_log ("Error in negotiating Kerberos continuation",WARN);
yuuji@0 186 (*responder) (stream,NIL,0);
yuuji@0 187 /* don't need context any more */
yuuji@0 188 gss_delete_sec_context (&smn,&ctx,NIL);
yuuji@0 189 break;
yuuji@0 190 }
yuuji@0 191 }
yuuji@0 192
yuuji@0 193 switch (smj) { /* done - deal with final condition */
yuuji@0 194 case GSS_S_COMPLETE:
yuuji@0 195 if (chal.value) fs_give ((void **) &chal.value);
yuuji@0 196 /* get prot mechanisms and max size */
yuuji@0 197 if ((*responder) (stream,resp.value ? resp.value : "",resp.length) &&
yuuji@0 198 (chal.value = (*challenger) (stream,(unsigned long *)&chal.length))&&
yuuji@0 199 (gss_unwrap (&smn,ctx,&chal,&resp,&conf,&qop) == GSS_S_COMPLETE) &&
yuuji@0 200 (resp.length >= 4) && (*((char *) resp.value) & AUTH_GSSAPI_P_NONE)){
yuuji@0 201 /* make copy of flags and length */
yuuji@0 202 memcpy (tmp,resp.value,4);
yuuji@0 203 gss_release_buffer (&smn,&resp);
yuuji@0 204 /* no session protection */
yuuji@0 205 tmp[0] = AUTH_GSSAPI_P_NONE;
yuuji@0 206 /* install user name */
yuuji@0 207 strcpy (tmp+4,strcpy (user,mb->user[0] ? mb->user : myusername ()));
yuuji@0 208 buf.value = tmp; buf.length = strlen (user) + 4;
yuuji@0 209 /* successful negotiation */
yuuji@0 210 switch (smj = gss_wrap (&smn,ctx,NIL,qop,&buf,&conf,&resp)) {
yuuji@0 211 case GSS_S_COMPLETE:
yuuji@0 212 if ((*responder) (stream,resp.value,resp.length)) ret = T;
yuuji@0 213 gss_release_buffer (&smn,&resp);
yuuji@0 214 break;
yuuji@0 215 default:
yuuji@0 216 do switch (dsmj = gss_display_status (&dsmn,smj,GSS_C_GSS_CODE,
yuuji@0 217 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 218 case GSS_S_COMPLETE:
yuuji@0 219 mctx = 0;
yuuji@0 220 case GSS_S_CONTINUE_NEEDED:
yuuji@0 221 sprintf (tmp,"Unknown gss_wrap failure: %s",(char *) resp.value);
yuuji@0 222 mm_log (tmp,WARN);
yuuji@0 223 gss_release_buffer (&dsmn,&resp);
yuuji@0 224 }
yuuji@0 225 while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 226 do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
yuuji@0 227 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 228 case GSS_S_COMPLETE:
yuuji@0 229 case GSS_S_CONTINUE_NEEDED:
yuuji@0 230 sprintf (tmp,"GSSAPI mechanism status: %s",(char *) resp.value);
yuuji@0 231 mm_log (tmp,WARN);
yuuji@0 232 gss_release_buffer (&dsmn,&resp);
yuuji@0 233 }
yuuji@0 234 while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 235 (*responder) (stream,NIL,0);
yuuji@0 236 }
yuuji@0 237 }
yuuji@0 238 /* flush final challenge */
yuuji@0 239 if (chal.value) fs_give ((void **) &chal.value);
yuuji@0 240 /* don't need context any more */
yuuji@0 241 gss_delete_sec_context (&smn,&ctx,NIL);
yuuji@0 242 break;
yuuji@0 243
yuuji@0 244 case GSS_S_CREDENTIALS_EXPIRED:
yuuji@0 245 if (chal.value) fs_give ((void **) &chal.value);
yuuji@0 246 /* retry if application kinits */
yuuji@0 247 if (ki && (*ki) (mb->host,"Kerberos credentials expired"))
yuuji@0 248 ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
yuuji@0 249 stream,user,NIL);
yuuji@0 250 else { /* application can't kinit */
yuuji@0 251 sprintf (tmp,"Kerberos credentials expired (try running kinit) for %s",
yuuji@0 252 mb->host);
yuuji@0 253 mm_log (tmp,WARN);
yuuji@0 254 (*responder) (stream,NIL,0);
yuuji@0 255 }
yuuji@0 256 break;
yuuji@0 257 case GSS_S_FAILURE:
yuuji@0 258 if (chal.value) fs_give ((void **) &chal.value);
yuuji@0 259 do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
yuuji@0 260 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 261 case GSS_S_COMPLETE: /* end of message, can kinit? */
yuuji@0 262 if (ki && kerberos_try_kinit (smn) &&
yuuji@0 263 (*ki) (mb->host,(char *) resp.value)) {
yuuji@0 264 gss_release_buffer (&dsmn,&resp);
yuuji@0 265 ret = auth_gssapi_client_work (challenger,chal,responder,service,mb,
yuuji@0 266 stream,user,NIL);
yuuji@0 267 break; /* done */
yuuji@0 268 }
yuuji@0 269 else (*responder) (stream,NIL,0);
yuuji@0 270 case GSS_S_CONTINUE_NEEDED:
yuuji@0 271 sprintf (tmp,kerberos_try_kinit (smn) ?
yuuji@0 272 "Kerberos error: %.80s (try running kinit) for %.80s" :
yuuji@0 273 "GSSAPI failure: %s for %.80s",(char *) resp.value,mb->host);
yuuji@0 274 mm_log (tmp,WARN);
yuuji@0 275 gss_release_buffer (&dsmn,&resp);
yuuji@0 276 } while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 277 break;
yuuji@0 278
yuuji@0 279 default: /* miscellaneous errors */
yuuji@0 280 if (chal.value) fs_give ((void **) &chal.value);
yuuji@0 281 do switch (dsmj = gss_display_status (&dsmn,smj,GSS_C_GSS_CODE,
yuuji@0 282 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 283 case GSS_S_COMPLETE:
yuuji@0 284 mctx = 0;
yuuji@0 285 case GSS_S_CONTINUE_NEEDED:
yuuji@0 286 sprintf (tmp,"Unknown GSSAPI failure: %s",(char *) resp.value);
yuuji@0 287 mm_log (tmp,WARN);
yuuji@0 288 gss_release_buffer (&dsmn,&resp);
yuuji@0 289 }
yuuji@0 290 while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 291 do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
yuuji@0 292 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 293 case GSS_S_COMPLETE:
yuuji@0 294 case GSS_S_CONTINUE_NEEDED:
yuuji@0 295 sprintf (tmp,"GSSAPI mechanism status: %s",(char *) resp.value);
yuuji@0 296 mm_log (tmp,WARN);
yuuji@0 297 gss_release_buffer (&dsmn,&resp);
yuuji@0 298 }
yuuji@0 299 while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 300 (*responder) (stream,NIL,0);
yuuji@0 301 break;
yuuji@0 302 }
yuuji@0 303 /* finished with credentials name */
yuuji@0 304 if (crname) gss_release_name (&smn,&crname);
yuuji@0 305 }
yuuji@0 306 return ret; /* return status */
yuuji@0 307 }
yuuji@0 308
yuuji@0 309 /* Server authenticator
yuuji@0 310 * Accepts: responder function
yuuji@0 311 * argument count
yuuji@0 312 * argument vector
yuuji@0 313 * Returns: authenticated user name or NIL
yuuji@0 314 */
yuuji@0 315
yuuji@0 316 char *auth_gssapi_server (authresponse_t responder,int argc,char *argv[])
yuuji@0 317 {
yuuji@0 318 char *ret = NIL;
yuuji@0 319 char tmp[MAILTMPLEN];
yuuji@0 320 unsigned long maxsize = htonl (AUTH_GSSAPI_C_MAXSIZE);
yuuji@0 321 int conf;
yuuji@0 322 OM_uint32 smj,smn,dsmj,dsmn,flags;
yuuji@0 323 OM_uint32 mctx = 0;
yuuji@0 324 gss_name_t crname,name;
yuuji@0 325 gss_OID mech;
yuuji@0 326 gss_buffer_desc chal,resp,buf;
yuuji@0 327 gss_cred_id_t crd;
yuuji@0 328 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
yuuji@0 329 gss_qop_t qop = GSS_C_QOP_DEFAULT;
yuuji@0 330 /* make service name */
yuuji@0 331 sprintf (tmp,"%s@%s",(char *) mail_parameters (NIL,GET_SERVICENAME,NIL),
yuuji@0 332 tcp_serverhost ());
yuuji@0 333 buf.length = strlen (buf.value = tmp);
yuuji@0 334 /* acquire credentials */
yuuji@0 335 if ((gss_import_name (&smn,&buf,GSS_C_NT_HOSTBASED_SERVICE,&crname)) ==
yuuji@0 336 GSS_S_COMPLETE) {
yuuji@0 337 if ((smj = gss_acquire_cred (&smn,crname,0,NIL,GSS_C_ACCEPT,&crd,NIL,NIL))
yuuji@0 338 == GSS_S_COMPLETE) {
yuuji@0 339 if (resp.value = (*responder) ("",0,(unsigned long *) &resp.length)) {
yuuji@0 340 do { /* negotiate authentication */
yuuji@0 341 smj = gss_accept_sec_context (&smn,&ctx,crd,&resp,
yuuji@0 342 GSS_C_NO_CHANNEL_BINDINGS,&name,&mech,
yuuji@0 343 &chal,&flags,NIL,NIL);
yuuji@0 344 /* don't need response any more */
yuuji@0 345 fs_give ((void **) &resp.value);
yuuji@0 346 switch (smj) { /* how did it go? */
yuuji@0 347 case GSS_S_COMPLETE: /* successful */
yuuji@0 348 case GSS_S_CONTINUE_NEEDED:
yuuji@0 349 if (chal.value) { /* send challenge, get next response */
yuuji@0 350 resp.value = (*responder) (chal.value,chal.length,
yuuji@0 351 (unsigned long *) &resp.length);
yuuji@0 352 gss_release_buffer (&smn,&chal);
yuuji@0 353 }
yuuji@0 354 break;
yuuji@0 355 }
yuuji@0 356 }
yuuji@0 357 while (resp.value && resp.length && (smj == GSS_S_CONTINUE_NEEDED));
yuuji@0 358
yuuji@0 359 /* successful exchange? */
yuuji@0 360 if ((smj == GSS_S_COMPLETE) &&
yuuji@0 361 (gss_display_name (&smn,name,&buf,&mech) == GSS_S_COMPLETE)) {
yuuji@0 362 /* send security and size */
yuuji@0 363 memcpy (resp.value = tmp,(void *) &maxsize,resp.length = 4);
yuuji@0 364 tmp[0] = AUTH_GSSAPI_P_NONE;
yuuji@0 365 if (gss_wrap (&smn,ctx,NIL,qop,&resp,&conf,&chal) == GSS_S_COMPLETE){
yuuji@0 366 resp.value = (*responder) (chal.value,chal.length,
yuuji@0 367 (unsigned long *) &resp.length);
yuuji@0 368 gss_release_buffer (&smn,&chal);
yuuji@0 369 if (gss_unwrap (&smn,ctx,&resp,&chal,&conf,&qop)==GSS_S_COMPLETE) {
yuuji@0 370 /* client request valid */
yuuji@0 371 if (chal.value && (chal.length > 4) &&
yuuji@0 372 (chal.length < (MAILTMPLEN - 1)) &&
yuuji@0 373 memcpy (tmp,chal.value,chal.length) &&
yuuji@0 374 (tmp[0] & AUTH_GSSAPI_P_NONE)) {
yuuji@0 375 /* tie off authorization ID */
yuuji@0 376 tmp[chal.length] = '\0';
yuuji@0 377 ret = kerberos_login (tmp+4,buf.value,argc,argv);
yuuji@0 378 }
yuuji@0 379 /* done with user name */
yuuji@0 380 gss_release_buffer (&smn,&chal);
yuuji@0 381 }
yuuji@0 382 /* finished with response */
yuuji@0 383 fs_give ((void **) &resp.value);
yuuji@0 384 }
yuuji@0 385 /* don't need name buffer any more */
yuuji@0 386 gss_release_buffer (&smn,&buf);
yuuji@0 387 }
yuuji@0 388 /* don't need client name any more */
yuuji@0 389 gss_release_name (&smn,&name);
yuuji@0 390 /* don't need context any more */
yuuji@0 391 if (ctx != GSS_C_NO_CONTEXT) gss_delete_sec_context (&smn,&ctx,NIL);
yuuji@0 392 }
yuuji@0 393 /* finished with credentials */
yuuji@0 394 gss_release_cred (&smn,&crd);
yuuji@0 395 }
yuuji@0 396
yuuji@0 397 else { /* can't acquire credentials! */
yuuji@0 398 if (gss_display_name (&dsmn,crname,&buf,&mech) == GSS_S_COMPLETE)
yuuji@0 399 SERVER_LOG ("Failed to acquire credentials for %s",buf.value);
yuuji@0 400 if (smj != GSS_S_FAILURE) do
yuuji@0 401 switch (dsmj = gss_display_status (&dsmn,smj,GSS_C_GSS_CODE,
yuuji@0 402 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 403 case GSS_S_COMPLETE:
yuuji@0 404 mctx = 0;
yuuji@0 405 case GSS_S_CONTINUE_NEEDED:
yuuji@0 406 SERVER_LOG ("Unknown GSSAPI failure: %s",resp.value);
yuuji@0 407 gss_release_buffer (&dsmn,&resp);
yuuji@0 408 }
yuuji@0 409 while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 410 do switch (dsmj = gss_display_status (&dsmn,smn,GSS_C_MECH_CODE,
yuuji@0 411 GSS_C_NO_OID,&mctx,&resp)) {
yuuji@0 412 case GSS_S_COMPLETE:
yuuji@0 413 case GSS_S_CONTINUE_NEEDED:
yuuji@0 414 SERVER_LOG ("GSSAPI mechanism status: %s",resp.value);
yuuji@0 415 gss_release_buffer (&dsmn,&resp);
yuuji@0 416 }
yuuji@0 417 while (dsmj == GSS_S_CONTINUE_NEEDED);
yuuji@0 418 }
yuuji@0 419 /* finished with credentials name */
yuuji@0 420 gss_release_name (&smn,&crname);
yuuji@0 421 }
yuuji@0 422 return ret; /* return status */
yuuji@0 423 }

UW-IMAP'd extensions by yuuji