~ubuntu-branches/ubuntu/precise/xdm/precise

« back to all changes in this revision

Viewing changes to greeter/greet.c

  • Committer: Bazaar Package Importer
  • Author(s): Julien Cristau
  • Date: 2008-10-05 20:55:43 UTC
  • mfrom: (7.1.7 intrepid)
  • Revision ID: james.westby@ubuntu.com-20081005205543-t9lgih96kbj1eidd
Tags: 1:1.1.8-5
Updated Polish debconf translation, thanks to Łukasz Paździora
(closes: #499073).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* $Xorg: greet.c,v 1.4 2001/02/09 02:05:41 xorgcvs Exp $ */
2
 
/* $XdotOrg: app/xdm/greeter/greet.c,v 1.3 2005/08/19 04:26:04 alanc Exp $ */
 
2
/* $XdotOrg: app/xdm/greeter/greet.c,v 1.5 2006/06/03 01:13:44 alanc Exp $ */
3
3
/*
4
4
 
5
5
Copyright 1988, 1998  The Open Group
27
27
from The Open Group.
28
28
 
29
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
 
30
58
/* $XFree86: xc/programs/xdm/greeter/greet.c,v 3.16tsi Exp $ */
31
59
 
32
60
/*
93
121
void    (*__xdm_endgrent)(void) = NULL;
94
122
#ifdef USESHADOW
95
123
struct spwd   *(*__xdm_getspnam)(GETSPNAM_ARGS) = NULL;
 
124
# ifndef QNX4
96
125
void   (*__xdm_endspent)(void) = NULL;
 
126
# endif /* QNX4 doesn't use endspent */
97
127
#endif
98
128
struct passwd   *(*__xdm_getpwnam)(GETPWNAM_ARGS) = NULL;
99
 
#ifdef linux
 
129
#if defined(linux) || defined(__GLIBC__)
100
130
void   (*__xdm_endpwent)(void) = NULL;
101
131
#endif
102
132
char     *(*__xdm_crypt)(CRYPT_ARGS) = NULL;
118
148
extern Display  *dpy;
119
149
 
120
150
static int      done, code;
121
 
static char     name[128], password[128];
 
151
#ifndef USE_PAM
 
152
static char     name[NAME_LEN], password[PASSWORD_LEN];
 
153
#endif
122
154
static Widget           toplevel;
123
155
static Widget           login;
124
156
static XtAppContext     context;
125
157
static XtIntervalId     pingTimeout;
126
158
 
 
159
#ifdef USE_PAM
 
160
static 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
 
 
171
struct myconv_data {
 
172
    struct display *d;
 
173
    struct greet_info *greet;
 
174
    char *username_display;
 
175
};
 
176
#endif
 
177
 
 
178
 
127
179
/*ARGSUSED*/
128
180
static void
129
181
GreetPingServer (
150
202
            data->name, strlen (data->passwd));
151
203
    switch (status) {
152
204
    case NOTIFY_OK:
 
205
#ifndef USE_PAM
153
206
        strncpy (name, data->name, sizeof(name));
154
207
        name[sizeof(name)-1] = '\0';
155
208
        strncpy (password, data->passwd, sizeof(password));
156
209
        password[sizeof(password)-1] = '\0';
157
 
        bzero (data->passwd, PASSWORD_LEN);
 
210
#endif
158
211
        code = 0;
159
212
        done = 1;
160
213
        break;
174
227
        done = 1;
175
228
        break;
176
229
    }
 
230
#ifndef USE_PAM
 
231
    if (done) {
 
232
        bzero (data->name, NAME_LEN);
 
233
        bzero (data->passwd, PASSWORD_LEN);
 
234
    }
 
235
#endif
177
236
}
178
237
 
179
238
static Display *
183
242
    int         i;
184
243
    static int  argc;
185
244
    Screen              *scrn;
186
 
    static char *argv[] = { "xlogin", 0 };
 
245
    static char *argv[] = { "xlogin", NULL };
187
246
    Display             *dpy;
188
247
#ifdef USE_XINERAMA
189
248
    XineramaScreenInfo *screens;
194
253
    argc = 1;
195
254
    XtToolkitInitialize ();
196
255
    context = XtCreateApplicationContext();
197
 
    dpy = XtOpenDisplay (context, d->name, "xlogin", "Xlogin", 0,0,
 
256
    dpy = XtOpenDisplay (context, d->name, "xlogin", "Xlogin", NULL, 0,
198
257
                         &argc, argv);
199
258
 
200
259
    if (!dpy)
201
 
        return 0;
 
260
        return NULL;
202
261
 
203
262
#ifdef XKB
204
263
    {
316
375
    Debug ("Done dispatch %s\n", d->name);
317
376
    if (code == 0)
318
377
    {
 
378
#ifndef USE_PAM
319
379
        char *ptr;
320
380
        unsigned int c,state = WHITESPACE;
321
381
 
334
394
 
335
395
        greet->name = ptr;
336
396
        greet->password = password;
 
397
#endif  /* USE_PAM */
337
398
        XtSetArg (arglist[0], XtNsessionArgument, (char *) &(greet->string));
338
399
        XtSetArg (arglist[1], XtNallowNullPasswd, (char *) &(greet->allow_null_passwd));
339
400
        XtSetArg (arglist[2], XtNallowRootLogin, (char *) &(greet->allow_root_login));
355
416
           d->name, greet->name);
356
417
#endif
357
418
    DrawFail (login);
 
419
#ifndef USE_PAM
358
420
    bzero (greet->name, strlen(greet->name));
359
421
    bzero (greet->password, strlen(greet->password));
 
422
#endif
360
423
}
361
424
 
362
 
 
 
425
_X_EXPORT
363
426
greet_user_rtn GreetUser(
364
427
    struct display          *d,
365
428
    Display                 ** dpy,
397
460
    __xdm_endgrent = dlfuncs->_endgrent;
398
461
#ifdef USESHADOW
399
462
    __xdm_getspnam = dlfuncs->_getspnam;
 
463
# ifndef QNX4
400
464
    __xdm_endspent = dlfuncs->_endspent;
 
465
# endif /* QNX4 doesn't use endspent */
401
466
#endif
402
467
    __xdm_getpwnam = dlfuncs->_getpwnam;
403
 
#ifdef linux
 
468
#if defined(linux) || defined(__GLIBC__)
404
469
    __xdm_endpwent = dlfuncs->_endpwent;
405
470
#endif
406
471
    __xdm_crypt = dlfuncs->_crypt;
423
488
#ifdef __OpenBSD__
424
489
    openlog("xdm", LOG_ODELAY, LOG_AUTH);
425
490
#endif
 
491
 
426
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 */
427
595
        /*
428
596
         * Greet user, requesting name/password
429
597
         */
440
608
            break;
441
609
        else
442
610
            FailedLogin (d, greet);
 
611
#endif
443
612
    }
444
613
    DeleteXloginResources (d, *dpy);
445
614
    CloseGreet (d);
496
665
 
497
666
    return Greet_Success;
498
667
}
 
668
 
 
669
 
 
670
#ifdef USE_PAM
 
671
static 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