Patches from pkgsrc-WIP
[oweals/cde.git] / cde / programs / dtlogin / verify.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*                                                                      *
24  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 /*
30  * xdm - display manager daemon
31  *
32  * $TOG: verify.c /main/7 1998/11/02 15:25:40 mgreess $
33  *
34  * Copyright 1988 Massachusetts Institute of Technology
35  *
36  * Permission to use, copy, modify, and distribute this software and its
37  * documentation for any purpose and without fee is hereby granted, provided
38  * that the above copyright notice appear in all copies and that both that
39  * copyright notice and this permission notice appear in supporting
40  * documentation, and that the name of M.I.T. not be used in advertising or
41  * publicity pertaining to distribution of the software without specific,
42  * written prior permission.  M.I.T. makes no representations about the
43  * suitability of this software for any purpose.  It is provided "as is"
44  * without express or implied warranty.
45  *
46  * Author:  Keith Packard, MIT X Consortium
47  */
48
49 /*
50  * verify.c
51  *
52  * typical unix verification routine.
53  */
54
55 # include       "dm.h"
56 # include       "vgmsg.h"
57 # include       "vgproto.h"
58
59 #include <X11/Xresource.h>
60
61 #ifdef _AIX
62 # include       <usersec.h>
63 #endif
64
65 # include       <pwd.h>
66 # ifdef NGROUPS
67 # include       <grp.h>
68 # endif
69
70 #ifdef sun
71 # include       <deflt.h>
72 #endif
73
74 struct passwd nobody = {
75         "Nobody", "***************"
76 };
77
78 static  char    *Pndefault      = "/etc/default/login";
79
80
81
82
83
84 extern char *_ExpandLang( char *string, char *lang );
85
86 int 
87 Verify(
88         struct display *d,
89         struct greet_info *greet,
90         struct verify_info *verify )
91 {
92         struct passwd   *p;
93         char            *shell, *home;
94         char            **argv;
95         FILE            *lastsession;
96         char            last_sess[MAXPATHLEN];
97         int             notify_dt;
98         int             i;
99
100         Debug ("Verify(): %s\n", greet->name);
101
102         /*
103          * The user has already been verified by the Greeter. This is
104          * really just to look up the rest of his environment. Better
105          * performance would be realized by having the Greeter look this up
106          * and pass it back in the pipe (saving an additional getpwnam).
107          */
108          
109         p = getpwnam (greet->name);
110         if (!p || strlen (greet->name) == 0) {
111             Debug ("Can't get user information for %s\n", greet->name);
112             return 0;
113         }
114
115 #ifdef BYPASSLOGIN
116         Debug ("BypassLogin = %d\n",d->bypassLogin);
117         if ( d->bypassLogin ) {
118             char *s = NULL;
119             if ( !strcmp (p->pw_name, "Nobody" ))
120                 s = "Greetless login failed; user invalid\n";
121             else if ( access ( p->pw_dir, F_OK ))
122                 s = "Greetless login failed; bad user home dir access\n";
123             else if ( p->pw_uid == 0 )
124                 s = "Greetless login failed; root bypass disallowed\n";
125             if (s) {
126                 Debug(s); LogError((unsigned char *) s);
127                 bzero(greet->password, strlen(greet->password));
128                 return 0;
129             }
130         }
131 #endif /* BYPASSLOGIN */
132
133 #ifdef AthenaWidgets
134 #ifdef BYPASSLOGIN 
135         if (strcmp(crypt(greet->password,p->pw_passwd),p->pw_passwd)
136             && !d->bypassLogin) {
137 #else
138         if (strcmp(crypt(greet->password,p->pw_passwd),p->pw_passwd)) {
139 #endif /* BYPASSLOGIN */
140             Debug ("verify failed\n");
141             bzero(greet->password, strlen(greet->password));
142             return 0;
143         }
144         Debug ("verify succeeded\n");
145         bzero(greet->password, strlen(greet->password));
146 #endif
147         Debug ("User information for %s acquired\n", greet->name);
148
149
150         verify->uid = p->pw_uid;
151
152 #ifdef __AFS
153         if ( IsVerifyName(VN_AFS) ) {
154             (void)setgid(p->pw_gid);
155             verify->groups[2] = p->pw_gid;
156         }
157 #else
158 #  ifdef NGROUPS
159         getGroups (greet->name, verify, p->pw_gid);
160 #  else
161         verify->gid = p->pw_gid;
162 #  endif
163 #endif /* __AFS */
164
165 #ifdef AUDIT
166         verify->audid  = p->pw_audid;
167         verify->audflg = p->pw_audflg;
168 #endif  
169
170         home = p->pw_dir;
171         shell = p->pw_shell;
172         argv = 0;
173
174         if(d->sessionType > NOTIFY_ALT_DTS)
175             notify_dt = NOTIFY_ALT_DTS;
176         else
177             notify_dt = d->sessionType;
178
179         switch (notify_dt) {
180         case NOTIFY_DT:
181         case NOTIFY_OK:
182             if(d->session)
183               argv = parseArgs (argv,d->session);
184               break;
185         case NOTIFY_ALT_DTS:
186             if((argv = setDt(d,argv,notify_dt)) == NULL)
187                 /*if no startup file, startup the regular desktop*/
188                if(d->session) {
189                   argv = parseArgs (argv,d->session);
190
191                Debug ("No Startup file \n");
192                }
193             break;
194         case NOTIFY_LAST_DT:
195             strcpy(last_sess,home);
196             strcat(last_sess,LAST_SESSION_FILE);
197
198             if((lastsession = fopen(last_sess,"r")) == NULL)  {
199             /* 
200              * if no lastsession file, execute the logically 
201              *          first alternate desktop
202              */
203                 if((argv = setDt(d,argv,notify_dt)) == NULL)
204                   if(d->session) {
205                     argv = parseArgs (argv,d->session);
206                     /* No altdts, set the Default Regular session */
207                     Debug ("No AltDestops in the resources file \n");
208                   }
209             }
210             else{
211                strcpy(last_sess,"\0");  
212                fgets(last_sess,MAXPATHLEN,lastsession);
213
214                if(access(last_sess, X_OK) != 0) {
215                   if((argv = setDt(d,argv,notify_dt)) == NULL)
216                     if(d->session){
217                       argv = parseArgs (argv,d->session);
218                       /* No altdts, set the Default Regular session */
219                       Debug ("No AltDestops in the resources file setting to %s  \n",argv[0]);
220                     }
221                }
222                else {
223                   argv = parseArgs (argv, last_sess);
224                }
225                fclose(lastsession);
226             }
227             break;
228         default:
229             break;
230         }
231         
232         if (greet->string)
233                 argv = parseArgs (argv, greet->string);
234         if (!argv)
235                 argv = parseArgs (argv, "xsession");
236         verify->argv = argv;
237         verify->userEnviron = userEnv (d, greet->name, home, shell,p);
238         Debug ("User environment:\n");
239         printEnv (verify->userEnviron);
240         verify->systemEnviron = systemEnv (d, greet->name, home);
241         Debug ("System environment:\n");
242         printEnv (verify->systemEnviron);
243         Debug ("End of environments\n");
244 #ifdef __osf__
245         if (setlogin(greet->name) == -1) {
246                 Debug ("setlogin failed for %s, errno = %d\n", greet->name,
247                 errno);
248         }
249 #endif /* __osf__ */
250         return 1;
251 }
252
253 char **
254 setDt(
255         struct display *d,
256         char **argv,
257         int     dt_type)
258 {
259 int             i;
260 char            *resources = NULL;
261 char            altdts[MAXPATHLEN];
262 char            altdtsclass[MAXPATHLEN];
263 char            altdtstart[MAXPATHLEN];
264 char            altdtstartclass[MAXPATHLEN];
265 int             adts;
266 XrmValue        value_dts;
267 char            *rmtype;
268 XrmValue        rmvalue;
269 int             altdtrequested;
270
271
272    if(!XresourceDB) {
273       Debug ("Verify - No resources \n");
274       return 0;
275    }
276
277  
278    if(dt_type == NOTIFY_LAST_DT) {
279       sprintf(altdts,"%s","Dtlogin*altDts");
280       sprintf(altdtsclass,"%s","Dtlogin*AltDts");
281  
282       if(XrmGetResource(XresourceDB, altdts, altdtsclass,
283         &rmtype, &value_dts) == True){
284         adts = atoi(value_dts.addr);
285         for(i = 0; i < adts; i++) {
286            sprintf(altdtstart,"%s%d","Dtlogin*altDtStart",i+1);
287            sprintf(altdtstartclass,"%s%d","Dtlogin*AltDtStart",i+1);
288            if(XrmGetResource(XresourceDB, altdtstart, altdtstartclass,
289                &rmtype, &rmvalue) == True){
290               Debug ("Start up file is %s\n",rmvalue.addr);
291               argv = parseArgs (argv, rmvalue.addr);
292               return argv;
293            }
294         }
295       }
296    }
297    else {
298             altdtrequested = d->sessionType - NOTIFY_ALT_DTS;
299                 
300             sprintf(altdtstart,"%s%d",
301                         "Dtlogin*altDtStart",altdtrequested);
302             sprintf(altdtstartclass,"%s%d",
303                         "Dtlogin*AltDtStart",altdtrequested);
304  
305             if(XrmGetResource(XresourceDB, altdtstart, altdtstartclass,
306                                         &rmtype, &rmvalue) == True){
307                 Debug ("Start up file is %s\n",rmvalue.addr);
308                 argv = parseArgs (argv, rmvalue.addr);
309                 return argv;
310             }
311    }
312  return 0;
313 }
314
315
316 char **
317 userEnv(
318         struct display *d,
319         char *user,
320         char *home,
321         char *shell,
322         struct passwd   *p)
323 {
324         char    **env;
325         char     *value;
326         char    **exp;
327         char     *Def_path;
328         char    *langlist = NULL;
329         
330 #ifdef _AIX
331        /*
332         * For AIX, we must delimit protected variables. This is done by
333         * adding special tags to the environment list. The setpenv()
334         * routine serched the environent for these special tags.
335         *
336         * NOTE: If you change the location of PENV_SYSSTR or PENV_USRSTR
337         *       in this environment list, you MUST change the index 
338         *       in session.c prior to the call to setpenv().
339         */
340         env = 0;
341         env = setEnv(env,PENV_SYSSTR,"");   /* protected vars */
342         env = setEnv(env,"LOGNAME",user);
343         env = setEnv(env,"LOGIN",user);
344         env = setEnv(env,PENV_USRSTR,"");   /* regular vars */
345
346 #else
347         env = 0;
348         env = setEnv (env,"LOGNAME", user);
349 #endif
350
351         for (exp = exportList; exp && *exp; ++exp)
352         {
353           value = getenv (*exp);
354           if (value)
355             env = setEnv (env, *exp, value);
356         }
357
358         env = setEnv (env, "DISPLAY", d->name);
359         env = setEnv (env, "HOME", home);
360         env = setEnv (env, "USER", user);
361
362 #ifdef sun
363         if ((Def_path = login_defaults(p,d)) != NULL) {
364           env = setEnv (env, "PATH", Def_path);
365           free(Def_path);
366         }
367 #else
368         if (d->userPath && strlen(d->userPath) > 0)
369           env = setEnv (env, "PATH", d->userPath);
370 #endif
371
372         env = setEnv (env, "SHELL", shell);
373
374         if (timeZone && strlen(timeZone) > 0 )
375           env = setEnv(env, "TZ", timeZone);
376
377         if ( d->langList && strlen(d->langList) > 0 )
378           langlist = d->langList;
379 #if defined (ENABLE_DYNAMIC_LANGLIST)
380         if (d->language && strlen(d->language) > 0)
381           langlist = d->language;
382 #else
383         else if (languageList && strlen(languageList) > 0 )
384           langlist = languageList;
385 #endif /* ENABLE_DYNAMIC_LANGLIST */
386
387         if (d->language && strlen(d->language) > 0)
388           env = setLang(d, env, langlist);
389
390 #if 0 /* setting LC_ALL can cause undesirable side effects -- bf@hp */
391 /*
392  * Don't set LC_MESSAGES to LANG since:
393  * 1) if LC_MESSAGES is unset, it will by default take on the value of LANG
394  * 2) if set, we don't want to override the user's setting
395  */
396             env = setEnv (env, "LC_ALL",      d->language);
397             env = setEnv (env, "LC_MESSAGES", d->language);
398 #endif
399
400 #if 0   /* setting XAUTHORITY here is a bug, needs further study... */
401         if (d->authFile)
402           env = setEnv (env, "XAUTHORITY", d->authFile);
403 #endif
404
405         if (d->displayType.location != Local)
406           env = setEnv (env, XFORCEINTERNET, "True");
407
408         if (d->environStr && strlen(d->environStr) > 0)
409           env = parseEnv(env, d->environStr);
410
411         /*
412          *  set SESSIONTYPE environment variable if requested by user, or
413          *  if the "dtlite" resource is set...
414          *
415          *  Note: the dtlite resource takes precedence over xdmMode.
416          */
417
418         if (d->dtlite == True)
419           d->sessionType = NOTIFY_DTLITE;
420         else if (d->xdmMode == True)
421           d->sessionType = NOTIFY_XDM;
422
423         switch (d->sessionType) {
424
425         case NOTIFY_DTLITE:
426             Debug("Setting SESSIONTYPE to 'dtlite'.\n");
427             env = setEnv(env, SESSIONTYPE, "dtlite");
428             break;
429
430         case NOTIFY_XDM:
431             Debug("Setting SESSIONTYPE to 'xdm'.\n");
432             env = setEnv(env, SESSIONTYPE, "xdm");
433             break;
434
435         case NOTIFY_DT:
436             Debug("Setting SESSIONTYPE to 'dt'.\n");
437             env = setEnv(env, SESSIONTYPE, "dt");
438             break;
439
440         default:
441             Debug("SESSIONTYPE NOT set.\n");
442             break;
443
444         }
445
446         return env;
447 }
448
449 /*
450  * read login defaults       
451  */
452 #ifdef sun
453 char *
454 login_defaults(
455         struct passwd *p,
456         struct display *d )
457 {
458         extern int defcntl();
459         register int  flags;
460         register char *ptr;
461         char *Def_path;
462         char *final_path = malloc(MAXPATHLEN);
463         char *element;
464  
465
466          if (defopen(Pndefault) == 0) {
467                 /*
468                  * ignore case
469                  * code taken from login.c 
470                  */
471                 flags = defcntl(DC_GETFLAGS, 0);
472                 TURNOFF(flags, DC_CASE);
473                 defcntl(DC_SETFLAGS, flags);
474  
475               if ( p->pw_uid == 0 ) {
476                 if ((Def_path = defread("SUPATH=")) != NULL)
477                         Def_path = strdup(Def_path);
478                 else
479                         Def_path = strdup(DEF_SUPATH);
480               }
481               else {
482                 if ((Def_path = defread("PATH=")) != NULL)
483                         Def_path = strdup(Def_path);
484                 else
485                         Def_path = strdup(DEF_PATH);
486               }
487          }
488
489         /*
490          * close the file..(/etc/default/login)
491          */
492         (void) defopen((char *)NULL);
493
494         Debug ("login_defaults():  \n");
495  
496          if (d->userPath && strlen(d->userPath) > 0) {
497             if(Def_path && strlen(Def_path) > 0)
498                 element = strtok(Def_path,":");
499             else
500                 return d->userPath;
501
502                 strcpy(final_path,d->userPath);
503
504            while(element) {
505              if((strstr(d->userPath,element)) == NULL) {
506                 strcat (final_path,":");
507                 strcat (final_path,element);
508              }
509              element = strtok(NULL,":");
510            }
511            return final_path;
512          }
513          else  {
514             if(Def_path && strlen(Def_path) > 0)
515                 return Def_path;        
516             else
517                 return 0;
518          }
519 }
520 #endif
521
522 char ** 
523 systemEnv( struct display *d, char *user, char *home )
524 {
525     char    **env;
526     char     *value;
527     char    **exp;
528     char     *langlist = NULL;
529         
530     env = 0;
531
532     for (exp = exportList; exp && *exp; ++exp)
533     {
534         value = getenv (*exp);
535         if (value)
536           env = setEnv (env, *exp, value);
537     }
538         
539     value = getenv("TZ");
540     if (value)
541       env = setEnv (env, "TZ", value);
542     else if (timeZone && strlen(timeZone) > 0 )
543       env = setEnv(env, "TZ", timeZone);
544
545     env = setEnv (env, "DISPLAY", d->name);
546     if (home)
547       env = setEnv (env, "HOME", home);
548     if (user)
549       env = setEnv (env, "USER", user);
550     env = setEnv (env, "PATH", d->systemPath);
551     env = setEnv (env, "SHELL", d->systemShell);
552             
553     if ( d->langList && strlen(d->langList) > 0 )
554       langlist = d->langList;
555 #if defined (ENABLE_DYNAMIC_LANGLIST)
556     else if (d->language && strlen(d->language) > 0 )
557       langlist = d->language;
558 #else
559     else if (languageList && strlen(languageList) > 0 )
560       langlist = languageList;
561 #endif /* ENABLE_DYNAMIC_LANGLIST */
562  
563     if (d->language && strlen(d->language) > 0)
564       env = setLang(d, env, langlist);
565
566     if (d->displayType.location != Local)
567       env = setEnv (env, XFORCEINTERNET, "True");
568
569 #if defined (sun)
570     if (getEnv (env, "OPENWINHOME") == NULL) 
571       env = setEnv(env, "OPENWINHOME", "/usr/openwin");
572 #endif
573
574     return env;
575 }
576
577 #ifdef NGROUPS
578
579 #ifndef __hpux
580
581 /*
582  *  groupMember() not used in HP-UX
583  */
584  
585 int 
586 groupMember(
587         char *name,
588         char **members )
589 {
590         while (*members) {
591                 if (!strcmp (name, *members))
592                         return 1;
593                 ++members;
594         }
595         return 0;
596 }
597 #endif /* ! __hpux */
598
599
600 void
601 getGroups(
602         char *name,
603         struct verify_info *verify,
604         int gid )
605 {
606         int             ngroups;
607         struct group    *g;
608         int             i;
609
610         ngroups = 0;
611         verify->groups[ngroups++] = gid;
612         setgrent ();
613
614         /*
615          * if your system does not support "initgroups(3C)", activate   
616          * this code...
617          */
618
619 #if !(defined(__hpux) || defined(__osf__))
620         while ( (g = getgrent()) != NULL ) {
621                 /*
622                  * make the list unique
623                  */
624                 for (i = 0; i < ngroups; i++)
625                         if (verify->groups[i] == g->gr_gid)
626                                 break;
627                 if (i != ngroups)
628                         continue;
629                 if (groupMember (name, g->gr_mem)) {
630                         if (ngroups >= NGROUPS)
631                                 LogError(ReadCatalog(MC_LOG_SET,
632                                         MC_LOG_MORE_GRP,MC_DEF_LOG_MORE_GRP),
633                                         name, NGROUPS, g->gr_name);
634                         else
635                                 verify->groups[ngroups++] = g->gr_gid;
636                 }
637         }
638 #endif
639         verify->ngroups = ngroups;
640         endgrent ();
641 }
642 #endif