greet.c revision 145b7b3c
1/* $Xorg: greet.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ */ 2/* $XdotOrg: app/xdm/greeter/greet.c,v 1.5 2006/06/03 01:13:44 alanc Exp $ */ 3/* 4 5Copyright 1988, 1998 The Open Group 6 7Permission to use, copy, modify, distribute, and sell this software and its 8documentation for any purpose is hereby granted without fee, provided that 9the above copyright notice appear in all copies and that both that 10copyright notice and this permission notice appear in supporting 11documentation. 12 13The above copyright notice and this permission notice shall be included 14in all copies or substantial portions of the Software. 15 16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22OTHER DEALINGS IN THE SOFTWARE. 23 24Except as contained in this notice, the name of The Open Group shall 25not be used in advertising or otherwise to promote the sale, use or 26other dealings in this Software without prior written authorization 27from The Open Group. 28 29*/ 30/* Copyright 2006 Sun Microsystems, Inc. All rights reserved. 31 * 32 * Permission is hereby granted, free of charge, to any person obtaining a 33 * copy of this software and associated documentation files (the 34 * "Software"), to deal in the Software without restriction, including 35 * without limitation the rights to use, copy, modify, merge, publish, 36 * distribute, and/or sell copies of the Software, and to permit persons 37 * to whom the Software is furnished to do so, provided that the above 38 * copyright notice(s) and this permission notice appear in all copies of 39 * the Software and that both the above copyright notice(s) and this 40 * permission notice appear in supporting documentation. 41 * 42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 43 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 44 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 45 * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 46 * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 47 * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 48 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 49 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 50 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 51 * 52 * Except as contained in this notice, the name of a copyright holder 53 * shall not be used in advertising or otherwise to promote the sale, use 54 * or other dealings in this Software without prior written authorization 55 * of the copyright holder. 56 */ 57 58/* $XFree86: xc/programs/xdm/greeter/greet.c,v 3.16tsi Exp $ */ 59 60/* 61 * xdm - display manager daemon 62 * Author: Keith Packard, X Consortium 63 * 64 * widget to get username/password 65 * 66 */ 67 68#ifdef HAVE_CONFIG_H 69# include "config.h" 70#endif 71 72#include <X11/Intrinsic.h> 73#include <X11/StringDefs.h> 74#include <X11/Shell.h> 75#include <X11/XKBlib.h> 76 77#ifdef USE_XINERAMA 78#include <X11/extensions/Xinerama.h> 79#endif 80 81#include "dm.h" 82#include "dm_error.h" 83#include "greet.h" 84#include "Login.h" 85 86#ifdef __OpenBSD__ 87#include <syslog.h> 88#endif 89 90#if defined(SECURE_RPC) && defined(sun) 91/* Go figure, there's no getdomainname() prototype available */ 92extern int getdomainname(char *name, size_t len); 93#endif 94 95#ifdef GREET_LIB 96/* 97 * Function pointers filled in by the initial call ito the library 98 */ 99 100int (*__xdm_PingServer)(struct display *d, Display *alternateDpy) = NULL; 101void (*__xdm_SessionPingFailed)(struct display *d) = NULL; 102void (*__xdm_Debug)(char * fmt, ...) = NULL; 103void (*__xdm_RegisterCloseOnFork)(int fd) = NULL; 104void (*__xdm_SecureDisplay)(struct display *d, Display *dpy) = NULL; 105void (*__xdm_UnsecureDisplay)(struct display *d, Display *dpy) = NULL; 106void (*__xdm_ClearCloseOnFork)(int fd) = NULL; 107void (*__xdm_SetupDisplay)(struct display *d) = NULL; 108void (*__xdm_LogError)(char * fmt, ...) = NULL; 109void (*__xdm_SessionExit)(struct display *d, int status, int removeAuth) = NULL; 110void (*__xdm_DeleteXloginResources)(struct display *d, Display *dpy) = NULL; 111int (*__xdm_source)(char **environ, char *file) = NULL; 112char **(*__xdm_defaultEnv)(void) = NULL; 113char **(*__xdm_setEnv)(char **e, char *name, char *value) = NULL; 114char **(*__xdm_putEnv)(const char *string, char **env) = NULL; 115char **(*__xdm_parseArgs)(char **argv, char *string) = NULL; 116void (*__xdm_printEnv)(char **e) = NULL; 117char **(*__xdm_systemEnv)(struct display *d, char *user, char *home) = NULL; 118void (*__xdm_LogOutOfMem)(char * fmt, ...) = NULL; 119void (*__xdm_setgrent)(void) = NULL; 120struct group *(*__xdm_getgrent)(void) = NULL; 121void (*__xdm_endgrent)(void) = NULL; 122#ifdef USESHADOW 123struct spwd *(*__xdm_getspnam)(GETSPNAM_ARGS) = NULL; 124# ifndef QNX4 125void (*__xdm_endspent)(void) = NULL; 126# endif /* QNX4 doesn't use endspent */ 127#endif 128struct passwd *(*__xdm_getpwnam)(GETPWNAM_ARGS) = NULL; 129#if defined(linux) || defined(__GLIBC__) 130void (*__xdm_endpwent)(void) = NULL; 131#endif 132char *(*__xdm_crypt)(CRYPT_ARGS) = NULL; 133#ifdef USE_PAM 134pam_handle_t **(*__xdm_thepamhp)(void) = NULL; 135#endif 136 137#endif 138 139#ifdef SECURE_RPC 140#include <rpc/rpc.h> 141#include <rpc/key_prot.h> 142#endif 143 144#ifdef K5AUTH 145#include <krb5/krb5.h> 146#endif 147 148extern Display *dpy; 149 150static int done, code; 151#ifndef USE_PAM 152static char name[NAME_LEN], password[PASSWORD_LEN]; 153#endif 154static Widget toplevel; 155static Widget login; 156static XtAppContext context; 157static XtIntervalId pingTimeout; 158 159#ifdef USE_PAM 160static int pamconv(int num_msg, 161#ifndef sun 162 const 163#endif 164 struct pam_message **msg, 165 struct pam_response **response, void *appdata_ptr); 166 167# define PAM_ERROR_PRINT(pamfunc, pamh) \ 168 LogError("%s failure: %s\n", pamfunc, pam_strerror(pamh, pam_error)) 169 170 171struct myconv_data { 172 struct display *d; 173 struct greet_info *greet; 174 char *username_display; 175}; 176#endif 177 178 179/*ARGSUSED*/ 180static void 181GreetPingServer ( 182 XtPointer closure, 183 XtIntervalId *intervalId) 184{ 185 struct display *d; 186 187 d = (struct display *) closure; 188 if (!PingServer (d, XtDisplay (toplevel))) 189 SessionPingFailed (d); 190 pingTimeout = XtAppAddTimeOut (context, d->pingInterval * 60 * 1000, 191 GreetPingServer, (closure)); 192} 193 194/*ARGSUSED*/ 195static void 196GreetDone ( 197 Widget w, 198 LoginData *data, 199 int status) 200{ 201 Debug ("GreetDone: %s, (password is %d long)\n", 202 data->name, strlen (data->passwd)); 203 switch (status) { 204 case NOTIFY_OK: 205#ifndef USE_PAM 206 strncpy (name, data->name, sizeof(name)); 207 name[sizeof(name)-1] = '\0'; 208 strncpy (password, data->passwd, sizeof(password)); 209 password[sizeof(password)-1] = '\0'; 210#endif 211 code = 0; 212 done = 1; 213 break; 214 case NOTIFY_ABORT: 215 Debug ("RESERVER_DISPLAY\n"); 216 code = RESERVER_DISPLAY; 217 done = 1; 218 break; 219 case NOTIFY_RESTART: 220 Debug ("REMANAGE_DISPLAY\n"); 221 code = REMANAGE_DISPLAY; 222 done = 1; 223 break; 224 case NOTIFY_ABORT_DISPLAY: 225 Debug ("UNMANAGE_DISPLAY\n"); 226 code = UNMANAGE_DISPLAY; 227 done = 1; 228 break; 229 } 230#ifndef USE_PAM 231 if (done) { 232 bzero (data->name, NAME_LEN); 233 bzero (data->passwd, PASSWORD_LEN); 234 } 235#endif 236} 237 238static Display * 239InitGreet (struct display *d) 240{ 241 Arg arglist[10]; 242 int i; 243 static int argc; 244 Screen *scrn; 245 static char *argv[] = { "xlogin", NULL }; 246 Display *dpy; 247#ifdef USE_XINERAMA 248 XineramaScreenInfo *screens; 249 int s_num; 250#endif 251 252 Debug ("greet %s\n", d->name); 253 argc = 1; 254 XtToolkitInitialize (); 255 context = XtCreateApplicationContext(); 256 dpy = XtOpenDisplay (context, d->name, "xlogin", "Xlogin", NULL, 0, 257 &argc, argv); 258 259 if (!dpy) 260 return NULL; 261 262#ifdef XKB 263 { 264 int opcode, evbase, errbase, majret, minret; 265 unsigned int value = XkbPCF_GrabsUseXKBStateMask; 266 if (XkbQueryExtension (dpy, &opcode, &evbase, &errbase, &majret, &minret)) { 267 if (!XkbSetPerClientControls (dpy, XkbPCF_GrabsUseXKBStateMask, &value)) 268 LogError ("%s\n", "SetPerClientControls failed"); 269 } 270 } 271#endif 272 RegisterCloseOnFork (ConnectionNumber (dpy)); 273 274 SecureDisplay (d, dpy); 275 276 i = 0; 277 scrn = XDefaultScreenOfDisplay(dpy); 278 XtSetArg(arglist[i], XtNscreen, scrn); i++; 279 XtSetArg(arglist[i], XtNargc, argc); i++; 280 XtSetArg(arglist[i], XtNargv, argv); i++; 281 282 toplevel = XtAppCreateShell ((String) NULL, "Xlogin", 283 applicationShellWidgetClass, dpy, arglist, i); 284 285 i = 0; 286 XtSetArg (arglist[i], XtNnotifyDone, (XtPointer)GreetDone); i++; 287 if (!d->authorize || d->authorizations || !d->authComplain) 288 { 289 XtSetArg (arglist[i], XtNsecureSession, True); i++; 290 } 291 login = XtCreateManagedWidget ("login", loginWidgetClass, toplevel, 292 arglist, i); 293 XtRealizeWidget (toplevel); 294 295#ifdef USE_XINERAMA 296 if ( 297 XineramaIsActive(dpy) && 298 (screens = XineramaQueryScreens(dpy, &s_num)) != NULL 299 ) 300 { 301 XWarpPointer(dpy, None, XRootWindowOfScreen (scrn), 302 0, 0, 0, 0, 303 screens[0].x_org + screens[0].width / 2, 304 screens[0].y_org + screens[0].height / 2); 305 306 XFree(screens); 307 } 308 else 309#endif 310 XWarpPointer(dpy, None, XRootWindowOfScreen (scrn), 311 0, 0, 0, 0, 312 XWidthOfScreen(scrn) / 2, 313 XHeightOfScreen(scrn) / 2); 314 315 if (d->pingInterval) 316 { 317 pingTimeout = XtAppAddTimeOut (context, d->pingInterval * 60 * 1000, 318 GreetPingServer, (XtPointer) d); 319 } 320 return dpy; 321} 322 323static void 324CloseGreet (struct display *d) 325{ 326 Boolean allow; 327 Arg arglist[1]; 328 Display *dpy = XtDisplay(toplevel); 329 330 if (pingTimeout) 331 { 332 XtRemoveTimeOut (pingTimeout); 333 pingTimeout = 0; 334 } 335 UnsecureDisplay (d, dpy); 336 XtSetArg (arglist[0], XtNallowAccess, (char *) &allow); 337 XtGetValues (login, arglist, 1); 338 if (allow) 339 { 340 Debug ("Disabling access control\n"); 341 XSetAccessControl (dpy, DisableAccess); 342 } 343 XtDestroyWidget (toplevel); 344 ClearCloseOnFork (XConnectionNumber (dpy)); 345 XCloseDisplay (dpy); 346 Debug ("Greet connection closed\n"); 347} 348 349#define WHITESPACE 0 350#define ARGUMENT 1 351 352static int 353Greet (struct display *d, struct greet_info *greet) 354{ 355 XEvent event; 356 Arg arglist[3]; 357 358 XtSetArg (arglist[0], XtNallowAccess, False); 359 XtSetValues (login, arglist, 1); 360 361 Debug ("dispatching %s\n", d->name); 362 done = 0; 363 while (!done) { 364 XtAppNextEvent (context, &event); 365 switch (event.type) { 366 case MappingNotify: 367 XRefreshKeyboardMapping(&event.xmapping); 368 break; 369 default: 370 XtDispatchEvent (&event); 371 break; 372 } 373 } 374 XFlush (XtDisplay (toplevel)); 375 Debug ("Done dispatch %s\n", d->name); 376 if (code == 0) 377 { 378#ifndef USE_PAM 379 char *ptr; 380 unsigned int c,state = WHITESPACE; 381 382 /* 383 * Process the name string to get rid of white spaces. 384 */ 385 for (ptr = name; state == WHITESPACE; ptr++) 386 { 387 c = (unsigned int)(*ptr); 388 if (c == ' ') 389 continue; 390 391 state = ARGUMENT; 392 break; 393 } 394 395 greet->name = ptr; 396 greet->password = password; 397#endif /* USE_PAM */ 398 XtSetArg (arglist[0], XtNsessionArgument, (char *) &(greet->string)); 399 XtSetArg (arglist[1], XtNallowNullPasswd, (char *) &(greet->allow_null_passwd)); 400 XtSetArg (arglist[2], XtNallowRootLogin, (char *) &(greet->allow_root_login)); 401 XtGetValues (login, arglist, 3); 402 Debug ("sessionArgument: %s\n", greet->string ? greet->string : "<NULL>"); 403 } 404 return code; 405} 406 407 408static void 409FailedLogin (struct display *d, struct greet_info *greet) 410{ 411#ifdef __OpenBSD__ 412 syslog(LOG_NOTICE, "LOGIN FAILURE ON %s", 413 d->name); 414 syslog(LOG_AUTHPRIV|LOG_NOTICE, 415 "LOGIN FAILURE ON %s, %s", 416 d->name, greet->name); 417#endif 418 DrawFail (login); 419#ifndef USE_PAM 420 bzero (greet->name, strlen(greet->name)); 421 bzero (greet->password, strlen(greet->password)); 422#endif 423} 424 425_X_EXPORT 426greet_user_rtn GreetUser( 427 struct display *d, 428 Display ** dpy, 429 struct verify_info *verify, 430 struct greet_info *greet, 431 struct dlfuncs *dlfuncs) 432{ 433 int i; 434 435#ifdef GREET_LIB 436/* 437 * These must be set before they are used. 438 */ 439 __xdm_PingServer = dlfuncs->_PingServer; 440 __xdm_SessionPingFailed = dlfuncs->_SessionPingFailed; 441 __xdm_Debug = dlfuncs->_Debug; 442 __xdm_RegisterCloseOnFork = dlfuncs->_RegisterCloseOnFork; 443 __xdm_SecureDisplay = dlfuncs->_SecureDisplay; 444 __xdm_UnsecureDisplay = dlfuncs->_UnsecureDisplay; 445 __xdm_ClearCloseOnFork = dlfuncs->_ClearCloseOnFork; 446 __xdm_SetupDisplay = dlfuncs->_SetupDisplay; 447 __xdm_LogError = dlfuncs->_LogError; 448 __xdm_SessionExit = dlfuncs->_SessionExit; 449 __xdm_DeleteXloginResources = dlfuncs->_DeleteXloginResources; 450 __xdm_source = dlfuncs->_source; 451 __xdm_defaultEnv = dlfuncs->_defaultEnv; 452 __xdm_setEnv = dlfuncs->_setEnv; 453 __xdm_putEnv = dlfuncs->_putEnv; 454 __xdm_parseArgs = dlfuncs->_parseArgs; 455 __xdm_printEnv = dlfuncs->_printEnv; 456 __xdm_systemEnv = dlfuncs->_systemEnv; 457 __xdm_LogOutOfMem = dlfuncs->_LogOutOfMem; 458 __xdm_setgrent = dlfuncs->_setgrent; 459 __xdm_getgrent = dlfuncs->_getgrent; 460 __xdm_endgrent = dlfuncs->_endgrent; 461#ifdef USESHADOW 462 __xdm_getspnam = dlfuncs->_getspnam; 463# ifndef QNX4 464 __xdm_endspent = dlfuncs->_endspent; 465# endif /* QNX4 doesn't use endspent */ 466#endif 467 __xdm_getpwnam = dlfuncs->_getpwnam; 468#if defined(linux) || defined(__GLIBC__) 469 __xdm_endpwent = dlfuncs->_endpwent; 470#endif 471 __xdm_crypt = dlfuncs->_crypt; 472#ifdef USE_PAM 473 __xdm_thepamhp = dlfuncs->_thepamhp; 474#endif 475#endif 476 477 *dpy = InitGreet (d); 478 /* 479 * Run the setup script - note this usually will not work when 480 * the server is grabbed, so we don't even bother trying. 481 */ 482 if (!d->grabServer) 483 SetupDisplay (d); 484 if (!*dpy) { 485 LogError ("Cannot reopen display %s for greet window\n", d->name); 486 exit (RESERVER_DISPLAY); 487 } 488#ifdef __OpenBSD__ 489 openlog("xdm", LOG_ODELAY, LOG_AUTH); 490#endif 491 492 for (;;) { 493#ifdef USE_PAM 494 495 /* Run PAM conversation */ 496 pam_handle_t **pamhp = thepamhp(); 497 int pam_error; 498 unsigned int pam_flags = 0; 499 struct myconv_data pcd = { d, greet, NULL }; 500 struct pam_conv pc = { pamconv, &pcd }; 501 const char * pam_fname; 502 char * username; 503 const char * login_prompt; 504 505 506 SetPrompt(login, 0, NULL, LOGIN_PROMPT_NOT_SHOWN, False); 507 login_prompt = GetPrompt(login, LOGIN_PROMPT_USERNAME); 508 SetPrompt(login, 1, NULL, LOGIN_PROMPT_NOT_SHOWN, False); 509 510#define RUN_AND_CHECK_PAM_ERROR(function, args) \ 511 do { \ 512 pam_error = function args; \ 513 if (pam_error != PAM_SUCCESS) { \ 514 PAM_ERROR_PRINT(#function, *pamhp); \ 515 goto pam_done; \ 516 } \ 517 } while (0) 518 519 520 RUN_AND_CHECK_PAM_ERROR(pam_start, 521 ("xdm", NULL, &pc, pamhp)); 522 523 /* Set default login prompt to xdm's default from Xresources */ 524 if (login_prompt != NULL) { 525 RUN_AND_CHECK_PAM_ERROR(pam_set_item, 526 (*pamhp, PAM_USER_PROMPT, login_prompt)); 527 } 528 529 if (d->name[0] != ':') { /* Displaying to remote host */ 530 char *hostname = strdup(d->name); 531 532 if (hostname == NULL) { 533 LogOutOfMem("GreetUser"); 534 } else { 535 char *colon = strrchr(hostname, ':'); 536 537 if (colon != NULL) 538 *colon = '\0'; 539 540 RUN_AND_CHECK_PAM_ERROR(pam_set_item, 541 (*pamhp, PAM_RHOST, hostname)); 542 free(hostname); 543 } 544 } else 545 RUN_AND_CHECK_PAM_ERROR(pam_set_item, (*pamhp, PAM_TTY, d->name)); 546 547 if (!greet->allow_null_passwd) { 548 pam_flags |= PAM_DISALLOW_NULL_AUTHTOK; 549 } 550 RUN_AND_CHECK_PAM_ERROR(pam_authenticate, 551 (*pamhp, pam_flags)); 552 553 /* handle expired passwords */ 554 pam_error = pam_acct_mgmt(*pamhp, pam_flags); 555 pam_fname = "pam_acct_mgmt"; 556 if (pam_error == PAM_NEW_AUTHTOK_REQD) { 557 ShowChangePasswdMessage(login); 558 do { 559 pam_error = pam_chauthtok(*pamhp, PAM_CHANGE_EXPIRED_AUTHTOK); 560 } while ((pam_error == PAM_AUTHTOK_ERR) || 561 (pam_error == PAM_TRY_AGAIN)); 562 pam_fname = "pam_chauthtok"; 563 } 564 if (pam_error != PAM_SUCCESS) { 565 PAM_ERROR_PRINT(pam_fname, *pamhp); 566 goto pam_done; 567 } 568 569 RUN_AND_CHECK_PAM_ERROR(pam_setcred, 570 (*pamhp, 0)); 571 RUN_AND_CHECK_PAM_ERROR(pam_get_item, 572 (*pamhp, PAM_USER, (void *) &username)); 573 if (username != NULL) { 574 Debug("PAM_USER: %s\n", username); 575 greet->name = username; 576 greet->password = NULL; 577 } 578 579 pam_done: 580 if (code != 0) 581 { 582 CloseGreet (d); 583 SessionExit (d, code, FALSE); 584 } 585 if ((pam_error == PAM_SUCCESS) && (Verify (d, greet, verify))) { 586 SetPrompt (login, 1, "Login Successful", LOGIN_TEXT_INFO, False); 587 SetValue (login, 1, NULL); 588 break; 589 } else { 590 RUN_AND_CHECK_PAM_ERROR(pam_end, 591 (*pamhp, pam_error)); 592 FailedLogin (d, greet); 593 } 594#else /* not PAM */ 595 /* 596 * Greet user, requesting name/password 597 */ 598 code = Greet (d, greet); 599 if (code != 0) 600 { 601 CloseGreet (d); 602 SessionExit (d, code, FALSE); 603 } 604 /* 605 * Verify user 606 */ 607 if (Verify (d, greet, verify)) 608 break; 609 else 610 FailedLogin (d, greet); 611#endif 612 } 613 DeleteXloginResources (d, *dpy); 614 CloseGreet (d); 615 Debug ("Greet loop finished\n"); 616 /* 617 * Run system-wide initialization file 618 */ 619 if (source (verify->systemEnviron, d->startup) != 0) 620 { 621 Debug ("Startup program %s exited with non-zero status\n", 622 d->startup); 623 SessionExit (d, OBEYSESS_DISPLAY, FALSE); 624 } 625 /* 626 * for user-based authorization schemes, 627 * add the user to the server's allowed "hosts" list. 628 */ 629 for (i = 0; i < d->authNum; i++) 630 { 631#ifdef SECURE_RPC 632 if (d->authorizations[i]->name_length == 9 && 633 memcmp(d->authorizations[i]->name, "SUN-DES-1", 9) == 0) 634 { 635 XHostAddress addr; 636 char netname[MAXNETNAMELEN+1]; 637 char domainname[MAXNETNAMELEN+1]; 638 639 getdomainname(domainname, sizeof domainname); 640 user2netname (netname, verify->uid, domainname); 641 addr.family = FamilyNetname; 642 addr.length = strlen (netname); 643 addr.address = netname; 644 XAddHost (*dpy, &addr); 645 } 646#endif 647#ifdef K5AUTH 648 if (d->authorizations[i]->name_length == 14 && 649 memcmp(d->authorizations[i]->name, "MIT-KERBEROS-5", 14) == 0) 650 { 651 /* Update server's auth file with user-specific info. 652 * Don't need to AddHost because X server will do that 653 * automatically when it reads the cache we are about 654 * to point it at. 655 */ 656 extern Xauth *Krb5GetAuthFor(); 657 658 XauDisposeAuth (d->authorizations[i]); 659 d->authorizations[i] = 660 Krb5GetAuthFor(14, "MIT-KERBEROS-5", d->name); 661 SaveServerAuthorizations (d, d->authorizations, d->authNum); 662 } 663#endif 664 } 665 666 return Greet_Success; 667} 668 669 670#ifdef USE_PAM 671static int pamconv(int num_msg, 672#ifndef sun 673 const 674#endif 675 struct pam_message **msg, 676 struct pam_response **response, void *appdata_ptr) 677{ 678 int i; 679 int greetCode; 680 int status = PAM_SUCCESS; 681 const char *pam_msg_styles[5] 682 = { "<invalid pam msg style>", 683 "PAM_PROMPT_ECHO_OFF", "PAM_PROMPT_ECHO_ON", 684 "PAM_ERROR_MSG", "PAM_TEXT_INFO" } ; 685 686 struct pam_message *m; 687 struct pam_response *r; 688 689 struct myconv_data *d = (struct myconv_data *) appdata_ptr; 690 691 pam_handle_t **pamhp = thepamhp(); 692 693 *response = calloc(num_msg, sizeof (struct pam_response)); 694 if (*response == NULL) 695 return (PAM_BUF_ERR); 696 697 m = *msg; 698 r = *response; 699 700 for (i = 0; i < num_msg; i++ , m++ , r++) { 701 char *username; 702 int promptId = 0; 703 loginPromptState pStyle = LOGIN_PROMPT_ECHO_OFF; 704 705 if ((pam_get_item(*pamhp, PAM_USER, (void *) &username) == PAM_SUCCESS) 706 && (username != NULL) && (*username != '\0')) { 707 SetPrompt(login, LOGIN_PROMPT_USERNAME, 708 NULL, LOGIN_TEXT_INFO, False); 709 SetValue(login, LOGIN_PROMPT_USERNAME, username); 710 promptId = 1; 711 } 712 713 Debug("pam_msg: %s (%d): '%s'\n", 714 ((m->msg_style > 0) && (m->msg_style <= 4)) ? 715 pam_msg_styles[m->msg_style] : pam_msg_styles[0], 716 m->msg_style, m->msg); 717 718 switch (m->msg_style) { 719 case PAM_ERROR_MSG: 720 ErrorMessage(login, m->msg, True); 721 break; 722 723 case PAM_TEXT_INFO: 724 SetPrompt (login, promptId, m->msg, LOGIN_TEXT_INFO, True); 725 SetValue (login, promptId, NULL); 726 break; 727 728 case PAM_PROMPT_ECHO_ON: 729 pStyle = LOGIN_PROMPT_ECHO_ON; 730 /* FALLTHROUGH */ 731 case PAM_PROMPT_ECHO_OFF: 732 SetPrompt (login, promptId, m->msg, pStyle, False); 733 SetValue (login, promptId, NULL); 734 greetCode = Greet (d->d, d->greet); 735 if (greetCode != 0) { 736 status = PAM_CONV_ERR; 737 goto pam_error; 738 } else { 739 r->resp = strdup(GetValue(login, promptId)); 740 SetValue(login, promptId, NULL); 741 if (r->resp == NULL) { 742 status = PAM_BUF_ERR; 743 goto pam_error; 744 } 745 /* Debug("pam_resp: '%s'\n", r->resp); */ 746 } 747 break; 748 749 default: 750 LogError("Unknown PAM msg_style: %d\n", m->msg_style); 751 } 752 } 753 pam_error: 754 if (status != PAM_SUCCESS) { 755 /* free responses */ 756 r = *response; 757 for (i = 0; i < num_msg; i++, r++) { 758 if (r->resp) { 759 bzero(r->resp, strlen(r->resp)); 760 free(r->resp); 761 } 762 } 763 free(*response); 764 *response = NULL; 765 } 766 return status; 767} 768#endif 769