dtprintinfo: Coverity 89561
[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 libraries 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             snprintf(last_sess, sizeof(last_sess), "%s%s", home, LAST_SESSION_FILE);
196
197             if((lastsession = fopen(last_sess,"r")) == NULL)  {
198             /* 
199              * if no lastsession file, execute the logically 
200              *          first alternate desktop
201              */
202                 if((argv = setDt(d,argv,notify_dt)) == NULL)
203                   if(d->session) {
204                     argv = parseArgs (argv,d->session);
205                     /* No altdts, set the Default Regular session */
206                     Debug ("No AltDestops in the resources file \n");
207                   }
208             }
209             else{
210                strcpy(last_sess,"\0");  
211                fgets(last_sess,MAXPATHLEN,lastsession);
212
213                if(access(last_sess, X_OK) != 0) {
214                   if((argv = setDt(d,argv,notify_dt)) == NULL)
215                     if(d->session){
216                       argv = parseArgs (argv,d->session);
217                       /* No altdts, set the Default Regular session */
218                       Debug ("No AltDestops in the resources file setting to %s  \n",argv[0]);
219                     }
220                }
221                else {
222                   argv = parseArgs (argv, last_sess);
223                }
224                fclose(lastsession);
225             }
226             break;
227         default:
228             break;
229         }
230         
231         if (greet->string)
232                 argv = parseArgs (argv, greet->string);
233         if (!argv)
234                 argv = parseArgs (argv, "xsession");
235         verify->argv = argv;
236         verify->userEnviron = userEnv (d, greet->name, home, shell,p);
237         Debug ("User environment:\n");
238         printEnv (verify->userEnviron);
239         verify->systemEnviron = systemEnv (d, greet->name, home);
240         Debug ("System environment:\n");
241         printEnv (verify->systemEnviron);
242         Debug ("End of environments\n");
243         return 1;
244 }
245
246 char **
247 setDt(
248         struct display *d,
249         char **argv,
250         int     dt_type)
251 {
252 int             i;
253 char            *resources = NULL;
254 char            altdts[MAXPATHLEN];
255 char            altdtsclass[MAXPATHLEN];
256 char            altdtstart[MAXPATHLEN];
257 char            altdtstartclass[MAXPATHLEN];
258 int             adts;
259 XrmValue        value_dts;
260 char            *rmtype;
261 XrmValue        rmvalue;
262 int             altdtrequested;
263
264
265    if(!XresourceDB) {
266       Debug ("Verify - No resources \n");
267       return 0;
268    }
269
270  
271    if(dt_type == NOTIFY_LAST_DT) {
272       sprintf(altdts,"%s","Dtlogin*altDts");
273       sprintf(altdtsclass,"%s","Dtlogin*AltDts");
274  
275       if(XrmGetResource(XresourceDB, altdts, altdtsclass,
276         &rmtype, &value_dts) == True){
277         adts = atoi(value_dts.addr);
278         for(i = 0; i < adts; i++) {
279            sprintf(altdtstart,"%s%d","Dtlogin*altDtStart",i+1);
280            sprintf(altdtstartclass,"%s%d","Dtlogin*AltDtStart",i+1);
281            if(XrmGetResource(XresourceDB, altdtstart, altdtstartclass,
282                &rmtype, &rmvalue) == True){
283               Debug ("Start up file is %s\n",rmvalue.addr);
284               argv = parseArgs (argv, rmvalue.addr);
285               return argv;
286            }
287         }
288       }
289    }
290    else {
291             altdtrequested = d->sessionType - NOTIFY_ALT_DTS;
292                 
293             sprintf(altdtstart,"%s%d",
294                         "Dtlogin*altDtStart",altdtrequested);
295             sprintf(altdtstartclass,"%s%d",
296                         "Dtlogin*AltDtStart",altdtrequested);
297  
298             if(XrmGetResource(XresourceDB, altdtstart, altdtstartclass,
299                                         &rmtype, &rmvalue) == True){
300                 Debug ("Start up file is %s\n",rmvalue.addr);
301                 argv = parseArgs (argv, rmvalue.addr);
302                 return argv;
303             }
304    }
305  return 0;
306 }
307
308
309 char **
310 userEnv(
311         struct display *d,
312         char *user,
313         char *home,
314         char *shell,
315         struct passwd   *p)
316 {
317         char    **env;
318         char     *value;
319         char    **exp;
320         char     *Def_path;
321         char    *langlist = NULL;
322         
323 #ifdef _AIX
324        /*
325         * For AIX, we must delimit protected variables. This is done by
326         * adding special tags to the environment list. The setpenv()
327         * routine serched the environent for these special tags.
328         *
329         * NOTE: If you change the location of PENV_SYSSTR or PENV_USRSTR
330         *       in this environment list, you MUST change the index 
331         *       in session.c prior to the call to setpenv().
332         */
333         env = 0;
334         env = setEnv(env,PENV_SYSSTR,"");   /* protected vars */
335         env = setEnv(env,"LOGNAME",user);
336         env = setEnv(env,"LOGIN",user);
337         env = setEnv(env,PENV_USRSTR,"");   /* regular vars */
338
339 #else
340         env = 0;
341         env = setEnv (env,"LOGNAME", user);
342 #endif
343
344         for (exp = exportList; exp && *exp; ++exp)
345         {
346           value = getenv (*exp);
347           if (value)
348             env = setEnv (env, *exp, value);
349         }
350
351         env = setEnv (env, "DISPLAY", d->name);
352         env = setEnv (env, "HOME", home);
353         env = setEnv (env, "USER", user);
354
355 #ifdef sun
356         if ((Def_path = login_defaults(p,d)) != NULL) {
357           env = setEnv (env, "PATH", Def_path);
358           free(Def_path);
359         }
360 #else
361         if (d->userPath && strlen(d->userPath) > 0)
362           env = setEnv (env, "PATH", d->userPath);
363 #endif
364
365         env = setEnv (env, "SHELL", shell);
366
367         if (timeZone && strlen(timeZone) > 0 )
368           env = setEnv(env, "TZ", timeZone);
369
370         if ( d->langList && strlen(d->langList) > 0 )
371           langlist = d->langList;
372 #if defined (ENABLE_DYNAMIC_LANGLIST)
373         if (d->language && strlen(d->language) > 0)
374           langlist = d->language;
375 #else
376         else if ( strlen(languageList) > 0 )
377           langlist = languageList;
378 #endif /* ENABLE_DYNAMIC_LANGLIST */
379
380         if (env && d->language && strlen(d->language) > 0)
381           env = setLang(d, env, langlist);
382
383 #if 0 /* setting LC_ALL can cause undesirable side effects -- bf@hp */
384 /*
385  * Don't set LC_MESSAGES to LANG since:
386  * 1) if LC_MESSAGES is unset, it will by default take on the value of LANG
387  * 2) if set, we don't want to override the user's setting
388  */
389             env = setEnv (env, "LC_ALL",      d->language);
390             env = setEnv (env, "LC_MESSAGES", d->language);
391 #endif
392
393 #if 0   /* setting XAUTHORITY here is a bug, needs further study... */
394         if (d->authFile)
395           env = setEnv (env, "XAUTHORITY", d->authFile);
396 #endif
397
398         if (d->displayType.location != Local)
399           env = setEnv (env, XFORCEINTERNET, "True");
400
401         if (d->environStr && strlen(d->environStr) > 0)
402           env = parseEnv(env, d->environStr);
403
404         /*
405          *  set SESSIONTYPE environment variable if requested by user, or
406          *  if the "dtlite" resource is set...
407          *
408          *  Note: the dtlite resource takes precedence over xdmMode.
409          */
410
411         if (d->dtlite == True)
412           d->sessionType = NOTIFY_DTLITE;
413         else if (d->xdmMode == True)
414           d->sessionType = NOTIFY_XDM;
415
416         switch (d->sessionType) {
417
418         case NOTIFY_DTLITE:
419             Debug("Setting SESSIONTYPE to 'dtlite'.\n");
420             env = setEnv(env, SESSIONTYPE, "dtlite");
421             break;
422
423         case NOTIFY_XDM:
424             Debug("Setting SESSIONTYPE to 'xdm'.\n");
425             env = setEnv(env, SESSIONTYPE, "xdm");
426             break;
427
428         case NOTIFY_DT:
429             Debug("Setting SESSIONTYPE to 'dt'.\n");
430             env = setEnv(env, SESSIONTYPE, "dt");
431             break;
432
433         default:
434             Debug("SESSIONTYPE NOT set.\n");
435             break;
436
437         }
438
439         return env;
440 }
441
442 /*
443  * read login defaults       
444  */
445 #ifdef sun
446 char *
447 login_defaults(
448         struct passwd *p,
449         struct display *d )
450 {
451         extern int defcntl();
452         int  flags;
453         char *ptr;
454         char *Def_path;
455         char *final_path = malloc(MAXPATHLEN);
456         char *element;
457  
458
459          if (defopen(Pndefault) == 0) {
460                 /*
461                  * ignore case
462                  * code taken from login.c 
463                  */
464                 flags = defcntl(DC_GETFLAGS, 0);
465                 TURNOFF(flags, DC_CASE);
466                 defcntl(DC_SETFLAGS, flags);
467  
468               if ( p->pw_uid == 0 ) {
469                 if ((Def_path = defread("SUPATH=")) != NULL)
470                         Def_path = strdup(Def_path);
471                 else
472                         Def_path = strdup(DEF_SUPATH);
473               }
474               else {
475                 if ((Def_path = defread("PATH=")) != NULL)
476                         Def_path = strdup(Def_path);
477                 else
478                         Def_path = strdup(DEF_PATH);
479               }
480          }
481
482         /*
483          * close the file..(/etc/default/login)
484          */
485         (void) defopen((char *)NULL);
486
487         Debug ("login_defaults():  \n");
488  
489          if (d->userPath && strlen(d->userPath) > 0) {
490             if(Def_path && strlen(Def_path) > 0)
491                 element = strtok(Def_path,":");
492             else
493                 return d->userPath;
494
495                 strcpy(final_path,d->userPath);
496
497            while(element) {
498              if((strstr(d->userPath,element)) == NULL) {
499                 strcat (final_path,":");
500                 strcat (final_path,element);
501              }
502              element = strtok(NULL,":");
503            }
504            return final_path;
505          }
506          else  {
507             if(Def_path && strlen(Def_path) > 0)
508                 return Def_path;        
509             else
510                 return 0;
511          }
512 }
513 #endif
514
515 char ** 
516 systemEnv( struct display *d, char *user, char *home )
517 {
518     char    **env;
519     char     *value;
520     char    **exp;
521     char     *langlist = NULL;
522         
523     env = 0;
524
525     for (exp = exportList; exp && *exp; ++exp)
526     {
527         value = getenv (*exp);
528         if (value)
529           env = setEnv (env, *exp, value);
530     }
531         
532     value = getenv("TZ");
533     if (value)
534       env = setEnv (env, "TZ", value);
535     else if (timeZone && strlen(timeZone) > 0 )
536       env = setEnv(env, "TZ", timeZone);
537
538     env = setEnv (env, "DISPLAY", d->name);
539     if (home)
540       env = setEnv (env, "HOME", home);
541     if (user)
542       env = setEnv (env, "USER", user);
543     env = setEnv (env, "PATH", d->systemPath);
544     env = setEnv (env, "SHELL", d->systemShell);
545             
546     if ( d->langList && strlen(d->langList) > 0 )
547       langlist = d->langList;
548 #if defined (ENABLE_DYNAMIC_LANGLIST)
549     else if (d->language && strlen(d->language) > 0 )
550       langlist = d->language;
551 #else
552     else if ( strlen(languageList) > 0 )
553       langlist = languageList;
554 #endif /* ENABLE_DYNAMIC_LANGLIST */
555  
556     if (d->language && strlen(d->language) > 0)
557       env = setLang(d, env, langlist);
558
559     if (d->displayType.location != Local)
560       env = setEnv (env, XFORCEINTERNET, "True");
561
562 #if defined (sun)
563     if (getEnv (env, "OPENWINHOME") == NULL) 
564       env = setEnv(env, "OPENWINHOME", "/usr/openwin");
565 #endif
566
567     return env;
568 }
569
570 #ifdef NGROUPS
571
572 #ifndef __hpux
573
574 /*
575  *  groupMember() not used in HP-UX
576  */
577  
578 int 
579 groupMember(
580         char *name,
581         char **members )
582 {
583         while (*members) {
584                 if (!strcmp (name, *members))
585                         return 1;
586                 ++members;
587         }
588         return 0;
589 }
590 #endif /* ! __hpux */
591
592
593 void
594 getGroups(
595         char *name,
596         struct verify_info *verify,
597         int gid )
598 {
599         int             ngroups;
600         struct group    *g;
601         int             i;
602
603         ngroups = 0;
604         verify->groups[ngroups++] = gid;
605         setgrent ();
606
607         /*
608          * if your system does not support "initgroups(3C)", activate   
609          * this code...
610          */
611
612 #if !(defined(__hpux))
613         while ( (g = getgrent()) != NULL ) {
614                 /*
615                  * make the list unique
616                  */
617                 for (i = 0; i < ngroups; i++)
618                         if (verify->groups[i] == g->gr_gid)
619                                 break;
620                 if (i != ngroups)
621                         continue;
622                 if (groupMember (name, g->gr_mem)) {
623                         if (ngroups >= NGROUPS)
624                                 LogError(ReadCatalog(MC_LOG_SET,
625                                         MC_LOG_MORE_GRP,MC_DEF_LOG_MORE_GRP),
626                                         name, NGROUPS, g->gr_name);
627                         else
628                                 verify->groups[ngroups++] = g->gr_gid;
629                 }
630         }
631 #endif
632         verify->ngroups = ngroups;
633         endgrent ();
634 }
635 #endif