Add GNU LGPL headers to all .c .C and .h files
[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;
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 #else
366         if (d->userPath && strlen(d->userPath) > 0)
367           env = setEnv (env, "PATH", d->userPath);
368 #endif
369
370         env = setEnv (env, "SHELL", shell);
371
372         if (timeZone && strlen(timeZone) > 0 )
373           env = setEnv(env, "TZ", timeZone);
374
375         if ( d->langList && strlen(d->langList) > 0 )
376           langlist = d->langList;
377 #if defined (ENABLE_DYNAMIC_LANGLIST)
378         if (d->language && strlen(d->language) > 0)
379           langlist = d->language;
380 #else
381         else if (languageList && strlen(languageList) > 0 )
382           langlist = languageList;
383 #endif /* ENABLE_DYNAMIC_LANGLIST */
384
385         if (d->language && strlen(d->language) > 0)
386           env = setLang(d, env, langlist);
387
388 #if 0 /* setting LC_ALL can cause undesirable side effects -- bf@hp */
389 /*
390  * Don't set LC_MESSAGES to LANG since:
391  * 1) if LC_MESSAGES is unset, it will by default take on the value of LANG
392  * 2) if set, we don't want to override the user's setting
393  */
394             env = setEnv (env, "LC_ALL",      d->language);
395             env = setEnv (env, "LC_MESSAGES", d->language);
396 #endif
397
398 #if 0   /* setting XAUTHORITY here is a bug, needs further study... */
399         if (d->authFile)
400           env = setEnv (env, "XAUTHORITY", d->authFile);
401 #endif
402
403         if (d->displayType.location != Local)
404           env = setEnv (env, XFORCEINTERNET, "True");
405
406         if (d->environStr && strlen(d->environStr) > 0)
407           env = parseEnv(env, d->environStr);
408
409         /*
410          *  set SESSIONTYPE environment variable if requested by user, or
411          *  if the "dtlite" resource is set...
412          *
413          *  Note: the dtlite resource takes precedence over xdmMode.
414          */
415
416         if (d->dtlite == True)
417           d->sessionType = NOTIFY_DTLITE;
418         else if (d->xdmMode == True)
419           d->sessionType = NOTIFY_XDM;
420
421         switch (d->sessionType) {
422
423         case NOTIFY_DTLITE:
424             Debug("Setting SESSIONTYPE to 'dtlite'.\n");
425             env = setEnv(env, SESSIONTYPE, "dtlite");
426             break;
427
428         case NOTIFY_XDM:
429             Debug("Setting SESSIONTYPE to 'xdm'.\n");
430             env = setEnv(env, SESSIONTYPE, "xdm");
431             break;
432
433         case NOTIFY_DT:
434             Debug("Setting SESSIONTYPE to 'dt'.\n");
435             env = setEnv(env, SESSIONTYPE, "dt");
436             break;
437
438         default:
439             Debug("SESSIONTYPE NOT set.\n");
440             break;
441
442         }
443
444         return env;
445 }
446
447 /*
448  * read login defaults       
449  */
450 #ifdef sun
451 char *
452 login_defaults(
453         struct passwd *p,
454         struct display *d )
455 {
456         extern int defcntl();
457         register int  flags;
458         register char *ptr;
459         char *Def_path;
460         char final_path[MAXPATHLEN];
461         char *element;
462  
463
464          if (defopen(Pndefault) == 0) {
465                 /*
466                  * ignore case
467                  * code taken from login.c 
468                  */
469                 flags = defcntl(DC_GETFLAGS, 0);
470                 TURNOFF(flags, DC_CASE);
471                 defcntl(DC_SETFLAGS, flags);
472  
473               if ( p->pw_uid == 0 ) {
474                 if ((Def_path = defread("SUPATH=")) != NULL)
475                         Def_path = strdup(Def_path);
476                 else
477                         Def_path = DEF_SUPATH;
478               }
479               else {
480                 if ((Def_path = defread("PATH=")) != NULL)
481                         Def_path = strdup(Def_path);
482                 else
483                         Def_path = DEF_PATH;
484               }
485          }
486
487         /*
488          * close the file..(/etc/default/login)
489          */
490         (void) defopen((char *)NULL);
491
492         Debug ("login_defaults():  \n");
493  
494          if (d->userPath && strlen(d->userPath) > 0) {
495             if(Def_path && strlen(Def_path) > 0)
496                 element = strtok(Def_path,":");
497             else
498                 return d->userPath;
499
500                 strcpy(final_path,d->userPath);
501
502            while(element) {
503              if((strstr(d->userPath,element)) == NULL) {
504                 strcat (final_path,":");
505                 strcat (final_path,element);
506              }
507              element = strtok(NULL,":");
508            }
509            return final_path;
510          }
511          else  {
512             if(Def_path && strlen(Def_path) > 0)
513                 return Def_path;        
514             else
515                 return 0;
516          }
517 }
518 #endif
519
520 char ** 
521 systemEnv( struct display *d, char *user, char *home )
522 {
523     char    **env;
524     char     *value;
525     char    **exp;
526     char     *langlist;
527         
528     env = 0;
529
530     for (exp = exportList; exp && *exp; ++exp)
531     {
532         value = getenv (*exp);
533         if (value)
534           env = setEnv (env, *exp, value);
535     }
536         
537     value = getenv("TZ");
538     if (value)
539       env = setEnv (env, "TZ", value);
540     else if (timeZone && strlen(timeZone) > 0 )
541       env = setEnv(env, "TZ", timeZone);
542
543     env = setEnv (env, "DISPLAY", d->name);
544     if (home)
545       env = setEnv (env, "HOME", home);
546     if (user)
547       env = setEnv (env, "USER", user);
548     env = setEnv (env, "PATH", d->systemPath);
549     env = setEnv (env, "SHELL", d->systemShell);
550             
551     if ( d->langList && strlen(d->langList) > 0 )
552       langlist = d->langList;
553 #if defined (ENABLE_DYNAMIC_LANGLIST)
554     else if (d->language && strlen(d->language) > 0 )
555       langlist = d->language;
556 #else
557     else if (languageList && strlen(languageList) > 0 )
558       langlist = languageList;
559 #endif /* ENABLE_DYNAMIC_LANGLIST */
560  
561     if (d->language && strlen(d->language) > 0)
562       env = setLang(d, env, langlist);
563
564     if (d->displayType.location != Local)
565       env = setEnv (env, XFORCEINTERNET, "True");
566
567 #if defined (sun)
568     if (getEnv (env, "OPENWINHOME") == NULL) 
569       env = setEnv(env, "OPENWINHOME", "/usr/openwin");
570 #endif
571
572     return env;
573 }
574
575 #ifdef NGROUPS
576
577 #ifndef __hpux
578
579 /*
580  *  groupMember() not used in HP-UX
581  */
582  
583 int 
584 groupMember(
585         char *name,
586         char **members )
587 {
588         while (*members) {
589                 if (!strcmp (name, *members))
590                         return 1;
591                 ++members;
592         }
593         return 0;
594 }
595 #endif /* ! __hpux */
596
597
598 void
599 getGroups(
600         char *name,
601         struct verify_info *verify,
602         int gid )
603 {
604         int             ngroups;
605         struct group    *g;
606         int             i;
607
608         ngroups = 0;
609         verify->groups[ngroups++] = gid;
610         setgrent ();
611
612         /*
613          * if your system does not support "initgroups(3C)", activate   
614          * this code...
615          */
616
617 #if !(defined(__hpux) || defined(__osf__))
618         while ( (g = getgrent()) != NULL ) {
619                 /*
620                  * make the list unique
621                  */
622                 for (i = 0; i < ngroups; i++)
623                         if (verify->groups[i] == g->gr_gid)
624                                 break;
625                 if (i != ngroups)
626                         continue;
627                 if (groupMember (name, g->gr_mem)) {
628                         if (ngroups >= NGROUPS)
629                                 LogError(ReadCatalog(MC_LOG_SET,
630                                         MC_LOG_MORE_GRP,MC_DEF_LOG_MORE_GRP),
631                                         name, NGROUPS, g->gr_name);
632                         else
633                                 verify->groups[ngroups++] = g->gr_gid;
634                 }
635         }
636 #endif
637         verify->ngroups = ngroups;
638         endgrent ();
639 }
640 #endif