Esempio n. 1
0
/*#define UVERBOSE*/
JNIEXPORT jobject JNICALL
Java_org_tanukisoftware_wrapper_WrapperManager_nativeGetUser(JNIEnv *env, jclass clazz, jboolean groups) {
    jclass wrapperUserClass;
    jmethodID constructor;
    jmethodID setGroup;
    jmethodID addGroup;
    uid_t uid;
    struct passwd *pw;
    gid_t ugid;
    jbyteArray jUser;
    jbyteArray jRealName;
    jbyteArray jHome;
    jbyteArray jShell;
    jobject wrapperUser = NULL;
    struct group *aGroup;
    int member;
    int i;
    gid_t ggid;
    jbyteArray jGroupName;

    /* Look for the WrapperUser class. Ignore failures as JNI throws an exception. */
    if ((wrapperUserClass = (*env)->FindClass(env, "org/tanukisoftware/wrapper/WrapperUNIXUser")) != NULL) {

        /* Look for the constructor. Ignore failures. */
        if ((constructor = (*env)->GetMethodID(env, wrapperUserClass, "<init>", "(II[B[B[B[B)V")) != NULL) {

            uid = geteuid();
            pw = getpwuid(uid);
            ugid = pw->pw_gid;

            /* Create the arguments to the constructor as java objects */

            /* User byte array */
            jUser = (*env)->NewByteArray(env, strlen(pw->pw_name));
            (*env)->SetByteArrayRegion(env, jUser, 0, strlen(pw->pw_name), (jbyte*)pw->pw_name);

            /* Real Name byte array */
            jRealName = (*env)->NewByteArray(env, strlen(pw->pw_gecos));
            (*env)->SetByteArrayRegion(env, jRealName, 0, strlen(pw->pw_gecos), (jbyte*)pw->pw_gecos);

            /* Home byte array */
            jHome = (*env)->NewByteArray(env, strlen(pw->pw_dir));
            (*env)->SetByteArrayRegion(env, jHome, 0, strlen(pw->pw_dir), (jbyte*)pw->pw_dir);

            /* Shell byte array */
            jShell = (*env)->NewByteArray(env, strlen(pw->pw_shell));
            (*env)->SetByteArrayRegion(env, jShell, 0, strlen(pw->pw_shell), (jbyte*)pw->pw_shell);

            /* Now create the new wrapperUser using the constructor arguments collected above. */
            wrapperUser = (*env)->NewObject(env, wrapperUserClass, constructor, uid, ugid, jUser, jRealName, jHome, jShell);

            /* If the caller requested the user's groups then look them up. */
            if (groups) {
               /* Set the user group. */
               if ((setGroup = (*env)->GetMethodID(env, wrapperUserClass, "setGroup", "(I[B)V")) != NULL) {
                   if ((aGroup = getgrgid(ugid)) != NULL) {
                       ggid = aGroup->gr_gid;

                       /* Group name byte array */
                       jGroupName = (*env)->NewByteArray(env, strlen(aGroup->gr_name));
                       (*env)->SetByteArrayRegion(env, jGroupName, 0, strlen(aGroup->gr_name), (jbyte*)aGroup->gr_name);

                        /* Add the group to the user. */
                       (*env)->CallVoidMethod(env, wrapperUser, setGroup, ggid, jGroupName);
                   }
               }

               /* Look for the addGroup method. Ignore failures. */
               if ((addGroup = (*env)->GetMethodID(env, wrapperUserClass, "addGroup", "(I[B)V")) != NULL) {

                   setgrent();
                   while ((aGroup = getgrent()) != NULL) {
                       /* Search the member list to decide whether or not the user is a member. */
                       member = 0;
                       i = 0;
                       while ((member == 0) && aGroup->gr_mem[i]) {
                           if (strcmp(aGroup->gr_mem[i], pw->pw_name) == 0) {
                               member = 1;
                           }
                           i++;
                       }

                       if (member) {
                           ggid = aGroup->gr_gid;

                           /* Group name byte array */
                           jGroupName = (*env)->NewByteArray(env, strlen(aGroup->gr_name));
                           (*env)->SetByteArrayRegion(env, jGroupName, 0, strlen(aGroup->gr_name), (jbyte*)aGroup->gr_name);

                           /* Add the group to the user. */
                           (*env)->CallVoidMethod(env, wrapperUser, addGroup, ggid, jGroupName);
                       }
                   }
                   endgrent();
                }
            }
        }
    }

    return wrapperUser;
}
Esempio n. 2
0
static int userrc_parse(struct vboxuser *vboxuser, unsigned char *home)
{
	unsigned char   tempsectname[VBOX_MAX_RCLINE_SIZE + 1];
	struct passwd	*pwdent;
	struct group	*grpent;
	unsigned char  *varusr;
	unsigned char  *vargrp;
	unsigned char  *varspc;
	unsigned char  *varmsk;
	int				 havegroup;

	static struct vboxrc rc_user_c[] =
	{
		{ "user"		, NULL },
		{ "group"	, NULL },
		{ "umask"	, NULL },
		{ "hdspace"	, NULL },
		{ NULL		, NULL }
	};

	xstrncpy(temppathname, SYSCONFDIR		 , PATH_MAX);
	xstrncat(temppathname, "/vboxgetty.conf", PATH_MAX);

	xstrncpy(tempsectname, "vboxgetty-phone-"	 , VBOX_MAX_RCLINE_SIZE);
	xstrncat(tempsectname, vboxuser->localphone, VBOX_MAX_RCLINE_SIZE);

	if (rc_read(rc_user_c, temppathname, tempsectname) < 0) return(-1);

	varusr = rc_get_entry(rc_user_c, "user"	);
	vargrp = rc_get_entry(rc_user_c, "group"	);
	varspc = rc_get_entry(rc_user_c, "hdspace");
	varmsk = rc_get_entry(rc_user_c, "umask"  );

	vboxuser->uid		= 0;
	vboxuser->gid		= 0;
	vboxuser->space	= 0;
	vboxuser->umask	= 0;

	strcpy(vboxuser->home, "");
	strcpy(vboxuser->name, "");

	if ((!varusr) || (!*varusr))
	{
		log_line(LOG_E, "You *must* specify a user name or a user id!\n");

		rc_free(rc_user_c);

		return(-1);
	}

	if (*varusr == '#')
		pwdent = getpwuid((uid_t)xstrtol(&varusr[1], 0));
	else
		pwdent = getpwnam(varusr);

	if (!pwdent)
	{
		log_line(LOG_E, "Unable to locate \"%s\" in systems passwd list.\n", varusr);

		rc_free(rc_user_c);

		return(-1);
	}

	vboxuser->uid = pwdent->pw_uid;
	vboxuser->gid = pwdent->pw_gid;

	if ((strlen(home) + strlen(pwdent->pw_name) + 2) < (PATH_MAX - 100))
	{
		xstrncpy(vboxuser->name, pwdent->pw_name, VBOXUSER_USERNAME);

		printstring(vboxuser->home, "%s/%s", home, pwdent->pw_name);
	}
	else
	{
		log_line(LOG_E, "Oops! Spool directory name and user name too long!\n");

		rc_free(rc_user_c);

		return(-1);
	}

	if ((vargrp) && (*vargrp))
	{
		havegroup = 0;

		setgrent();
					
		while ((grpent = getgrent()))
		{
			if (*vargrp == '#')
			{
				if (grpent->gr_gid == (gid_t)xstrtol(&vargrp[1], 0))
				{
					vboxuser->gid = grpent->gr_gid;
					havegroup	  = 1;
								
					break;
				}
			}
			else
			{
				if (strcmp(grpent->gr_name, vargrp) == 0)
				{
					vboxuser->gid = grpent->gr_gid;
					havegroup	  = 1;
								
					break;
				}
			}
		}
					
		endgrent();

		if (!havegroup)
		{
			log_line(LOG_E, "Unable to locate \"%s\" in systems group list.\n", vargrp);

			rc_free(rc_user_c);

			return(-1);
		}
	}

	if (varspc) vboxuser->space = xstrtol(varspc, 0);
	if (varmsk) vboxuser->umask = xstrtoo(varmsk, 0);

	log_line(LOG_D, "User \"%s\" (%d.%d) [%04o] will be used...\n", vboxuser->name, vboxuser->uid, vboxuser->gid, vboxuser->umask);

	rc_free(rc_user_c);

	return(0);
}
Esempio n. 3
0
int
grp_add(char *str)
{
	u_int indx;
	GRPT *pt;
	struct group *gr;
	gid_t gid;

	/*
	 * create the table if it doesn't exist
	 */
	if ((str == NULL) || (*str == '\0'))
		return(-1);
	if ((grptb == NULL) &&
 	    ((grptb = (GRPT **)calloc(GRP_TB_SZ, sizeof(GRPT *))) == NULL)) {
		paxwarn(1, "Unable to allocate memory fo group selection table");
		return(-1);
	}

	/*
	 * figure out user spec
	 */
	if (str[0] != '#') {
		/*
		 * it is a group name, \# escapes # as first char in group name
		 */
		if ((str[0] == '\\') && (str[1] == '#'))
			++str;
		if ((gr = getgrnam(str)) == NULL) {
			paxwarn(1,"Cannot determine gid for group name: %s", str);
			return(-1);
		}
		gid = gr->gr_gid;
	} else
#		ifdef NET2_STAT
		gid = (gid_t)atoi(str+1);
#		else
		gid = (gid_t)strtoul(str+1, NULL, 10);
#		endif
	endgrent();

	/*
	 * hash it and go down the hash chain (if any) looking for it
	 */
	indx = ((unsigned)gid) % GRP_TB_SZ;
	if ((pt = grptb[indx]) != NULL) {
		while (pt != NULL) {
			if (pt->gid == gid)
				return(0);
			pt = pt->fow;
		}
	}

	/*
	 * gid not in the table, add it to the front of the chain
	 */
	if ((pt = (GRPT *)malloc(sizeof(GRPT))) != NULL) {
		pt->gid = gid;
		pt->fow = grptb[indx];
		grptb[indx] = pt;
		return(0);
	}
	paxwarn(1, "Group selection table out of memory");
	return(-1);
}
Esempio n. 4
0
void real_endgrent() { endgrent(); }
Esempio n. 5
0
int drop_privs(void)
{
    struct group *gr;
    struct passwd *pw;
    char *endptr;
    int i;
    int do_setuid = 0;
    int do_setgid = 0;
    unsigned long groupid = 0;
    unsigned long userid = 0;

    if (config.group_name != NULL) {
        do_setgid = 1;
        if (!isdigit(config.group_name[0])) {
            gr = getgrnam(config.group_name);
            if(!gr){
                if(config.chroot_dir){
                    elog("ERROR: you have chrooted and must set numeric group ID.\n");
                    exit(1);
                }else{
                    elog("ERROR: couldn't get ID for group %s, group does not exist.", config.group_name)
                    exit(1);
                }
            }
            groupid = gr->gr_gid;
        } else {
            groupid = strtoul(config.group_name, &endptr, 10);
        }
    }

    if (config.user_name != NULL) {
        do_setuid = 1;
        do_setgid = 1;
        if (isdigit(config.user_name[0]) == 0) {
            pw = getpwnam(config.user_name);
            if (pw != NULL) {
                userid = pw->pw_uid;
            } else {
                printf("[E] User %s not found!\n", config.user_name);
            }
        } else {
            userid = strtoul(config.user_name, &endptr, 10);
            pw = getpwuid(userid);
        }

        if (config.group_name == NULL && pw != NULL) {
            groupid = pw->pw_gid;
        }
    }

    if (do_setgid) {
        if ((i = setgid(groupid)) < 0) {
            printf("Unable to set group ID: %s", strerror(i));
        }
   }

    endgrent();
    endpwent();

    if (do_setuid) {
        if (getuid() == 0 && initgroups(config.user_name, groupid) < 0) {
            printf("Unable to init group names (%s/%lu)", config.user_name,
                   groupid);
        }
        if ((i = setuid(userid)) < 0) {
            printf("Unable to set user ID: %s\n", strerror(i));
        }
    }
    return 0;
}
Esempio n. 6
0
static void
sysgroup_cleanup(void)
{
    if (need_setent)
	endgrent();
}
Esempio n. 7
0
int main (int argc, char **argv)
{
	struct group *gr;
	int found = 0;
	int num_users, i;

	/* Test getgrent() without setgrent() */

	for (i = 0; i < 100; i++) {
		gr = getgrent();

		/* This is supposed to work */

#if 0
		if (gr != NULL) {
			printf("FAIL: getgrent() with no setgrent()\n");
			return 1;
		}
#endif
	}

	/* Work out how many user till first domain group */

	num_users = 0;
	setgrent();

	while (1) {
		gr = getgrent();
		num_users++;

		if (gr == NULL) break;

		if (strchr(gr->gr_name, '/')) {
			found = 1;
			break;
		}

	}

	if (!found) {
		printf("FAIL: could not find any domain groups\n");
		return 1;
	}

	/* Test stopping getgrent in the middle of a set of users */

	endgrent();

	/* Test setgrent() without any getgrent() calls */

	setgrent();

	for (i = 0; i < (num_users - 1); i++) {
		getgrent();
	}

	endgrent();

	/* Test lots of setgrent() calls */

	for (i = 0; i < 100; i++) {
		setgrent();
	}

	/* Test lots of endgrent() calls */

	for (i = 0; i < 100; i++) {
		endgrent();
	}

	/* Everything's cool */

	printf("PASS\n");
	return 0;
}
Esempio n. 8
0
main(int argc, char *argv[])
#endif
{
    char            options[128] = "aAc:CdD::fhHI:l:L:m:M:n:p:P:qrsS:UvV-:Y:";
    int             arg, i, ret;
    int             dont_fork = 0, do_help = 0;
    int             log_set = 0;
    int             agent_mode = -1;
    char           *pid_file = NULL;
    char            option_compatability[] = "-Le";
#if HAVE_GETPID
    int fd;
    FILE           *PID;
#endif

#ifndef WIN32
    /*
     * close all non-standard file descriptors we may have
     * inherited from the shell.
     */
    for (i = getdtablesize() - 1; i > 2; --i) {
        (void) close(i);
    }
#endif /* #WIN32 */
    
    /*
     * register signals ASAP to prevent default action (usually core)
     * for signals during startup...
     */
#ifdef SIGTERM
    DEBUGMSGTL(("signal", "registering SIGTERM signal handler\n"));
    signal(SIGTERM, SnmpdShutDown);
#endif
#ifdef SIGINT
    DEBUGMSGTL(("signal", "registering SIGINT signal handler\n"));
    signal(SIGINT, SnmpdShutDown);
#endif
#ifdef SIGHUP
    signal(SIGHUP, SIG_IGN);   /* do not terminate on early SIGHUP */
#endif
#ifdef SIGUSR1
    DEBUGMSGTL(("signal", "registering SIGUSR1 signal handler\n"));
    signal(SIGUSR1, SnmpdDump);
#endif
#ifdef SIGPIPE
    DEBUGMSGTL(("signal", "registering SIGPIPE signal handler\n"));
    signal(SIGPIPE, SIG_IGN);   /* 'Inline' failure of wayward readers */
#endif
#ifdef SIGXFSZ
    signal(SIGXFSZ, SnmpdCatchRandomSignal);
#endif

#ifdef NETSNMP_NO_ROOT_ACCESS
    /*
     * Default to no.  
     */
    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
			   NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
#endif
    /*
     * Default to NOT running an AgentX master.  
     */
    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
			   NETSNMP_DS_AGENT_AGENTX_MASTER, 0);
    netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
                       NETSNMP_DS_AGENT_AGENTX_TIMEOUT, -1);
    netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
                       NETSNMP_DS_AGENT_AGENTX_RETRIES, -1);

    netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID,
                       NETSNMP_DS_AGENT_CACHE_TIMEOUT, 5);
    /*
     * Add some options if they are available.  
     */
#if HAVE_UNISTD_H
    strcat(options, "g:u:");
#endif
#if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE)
    strcat(options, "x:");
#endif
#ifdef USING_AGENTX_SUBAGENT_MODULE
    strcat(options, "X");
#endif

    /*
     * This is incredibly ugly, but it's probably the simplest way
     *  to handle the old '-L' option as well as the new '-Lx' style
     */
    for (i=0; i<argc; i++) {
        if (!strcmp(argv[i], "-L"))
            argv[i] = option_compatability;            
    }

#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
#ifdef WIN32
    snmp_log_syslogname(app_name_long);
#else
    snmp_log_syslogname(app_name);
#endif
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */
    netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
                          NETSNMP_DS_LIB_APPTYPE, app_name);

    /*
     * Now process options normally.  
     */
    while ((arg = getopt(argc, argv, options)) != EOF) {
        switch (arg) {
        case '-':
            if (strcasecmp(optarg, "help") == 0) {
                usage(argv[0]);
            }
            if (strcasecmp(optarg, "version") == 0) {
                version();
            }

            handle_long_opt(optarg);
            break;

        case 'a':
            log_addresses++;
            break;

        case 'A':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_LIB_APPEND_LOGFILES, 1);
            break;

        case 'c':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID, 
				      NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
            } else {
                usage(argv[0]);
            }
            break;

        case 'C':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
				   NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
            break;

        case 'd':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
                                   NETSNMP_DS_LIB_DUMP_PACKET,
                                   ++snmp_dump_packet);
            break;

        case 'D':
#ifdef NETSNMP_DISABLE_DEBUGGING
            fprintf(stderr, "Debugging not configured\n");
            exit(1);
#else
            debug_register_tokens(optarg);
            snmp_set_do_debugging(1);
#endif
            break;

        case 'f':
            dont_fork = 1;
            break;

#if HAVE_UNISTD_H
        case 'g':
            if (optarg != NULL) {
                char           *ecp;
                int             gid;

                gid = strtoul(optarg, &ecp, 10);
#if HAVE_GETGRNAM && HAVE_PWD_H
                if (*ecp) {
                    struct group  *info;

                    info = getgrnam(optarg);
                    gid = info ? info->gr_gid : -1;
                    endgrent();
                }
#endif
                if (gid < 0) {
                    fprintf(stderr, "Bad group id: %s\n", optarg);
                    exit(1);
                }
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_GROUPID, gid);
            } else {
                usage(argv[0]);
            }
            break;
#endif

        case 'h':
            usage(argv[0]);
            break;

        case 'H':
            do_help = 1;
            break;

        case 'I':
            if (optarg != NULL) {
                add_to_init_list(optarg);
            } else {
                usage(argv[0]);
            }
            break;

#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_FILE
        case 'l':
            printf("Warning: -l option is deprecated, use -Lf <file> instead\n");
            if (optarg != NULL) {
                if (strlen(optarg) > PATH_MAX) {
                    fprintf(stderr,
                            "%s: logfile path too long (limit %d chars)\n",
                            argv[0], PATH_MAX);
                    exit(1);
                }
                snmp_enable_filelog(optarg,
                                    netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
                                                           NETSNMP_DS_LIB_APPEND_LOGFILES));
                log_set = 1;
            } else {
                usage(argv[0]);
            }
            break;
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_FILE */

        case 'L':
	    if  (snmp_log_options( optarg, argc, argv ) < 0 ) {
                usage(argv[0]);
            }
            log_set = 1;
            break;

        case 'm':
            if (optarg != NULL) {
                setenv("MIBS", optarg, 1);
            } else {
                usage(argv[0]);
            }
            break;

        case 'M':
            if (optarg != NULL) {
                setenv("MIBDIRS", optarg, 1);
            } else {
                usage(argv[0]);
            }
            break;

        case 'n':
            if (optarg != NULL) {
                app_name = optarg;
                netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
                                      NETSNMP_DS_LIB_APPTYPE, app_name);
            } else {
                usage(argv[0]);
            }
            break;

        case 'P':
            printf("Warning: -P option is deprecated, use -p instead\n");
        case 'p':
            if (optarg != NULL) {
                pid_file = optarg;
            } else {
                usage(argv[0]);
            }
            break;

        case 'q':
            netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID, 
                                   NETSNMP_DS_LIB_QUICK_PRINT, 1);
            break;

        case 'r':
            netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
				      NETSNMP_DS_AGENT_NO_ROOT_ACCESS);
            break;

#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG
        case 's':
            printf("Warning: -s option is deprecated, use -Lsd instead\n");
            snmp_enable_syslog();
            log_set = 1;
            break;

        case 'S':
            printf("Warning: -S option is deprecated, use -Ls <facility> instead\n");
            if (optarg != NULL) {
                switch (*optarg) {
                case 'd':
                case 'D':
                    Facility = LOG_DAEMON;
                    break;
                case 'i':
                case 'I':
                    Facility = LOG_INFO;
                    break;
                case '0':
                    Facility = LOG_LOCAL0;
                    break;
                case '1':
                    Facility = LOG_LOCAL1;
                    break;
                case '2':
                    Facility = LOG_LOCAL2;
                    break;
                case '3':
                    Facility = LOG_LOCAL3;
                    break;
                case '4':
                    Facility = LOG_LOCAL4;
                    break;
                case '5':
                    Facility = LOG_LOCAL5;
                    break;
                case '6':
                    Facility = LOG_LOCAL6;
                    break;
                case '7':
                    Facility = LOG_LOCAL7;
                    break;
                default:
                    fprintf(stderr, "invalid syslog facility: -S%c\n",*optarg);
                    usage(argv[0]);
                }
                snmp_enable_syslog_ident(snmp_log_syslogname(NULL), Facility);
                log_set = 1;
            } else {
                fprintf(stderr, "no syslog facility specified\n");
                usage(argv[0]);
            }
            break;
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_SYSLOG */

        case 'U':
            netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, 
				      NETSNMP_DS_AGENT_LEAVE_PIDFILE);
            break;

#if HAVE_UNISTD_H
        case 'u':
            if (optarg != NULL) {
                char           *ecp;
                int             uid;

                uid = strtoul(optarg, &ecp, 10);
#if HAVE_GETPWNAM && HAVE_PWD_H
                if (*ecp) {
                    struct passwd  *info;

                    info = getpwnam(optarg);
                    uid = info ? info->pw_uid : -1;
                    endpwent();
                }
#endif
                if (uid < 0) {
                    fprintf(stderr, "Bad user id: %s\n", optarg);
                    exit(1);
                }
                netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_USERID, uid);
            } else {
                usage(argv[0]);
            }
            break;
#endif

        case 'v':
            version();

        case 'V':
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_VERBOSE, 1);
            break;

#if defined(USING_AGENTX_SUBAGENT_MODULE)|| defined(USING_AGENTX_MASTER_MODULE)
        case 'x':
            if (optarg != NULL) {
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, 
				      NETSNMP_DS_AGENT_X_SOCKET, optarg);
            } else {
                usage(argv[0]);
            }
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
				   NETSNMP_DS_AGENT_AGENTX_MASTER, 1);
            break;
#endif

        case 'X':
#if defined(USING_AGENTX_SUBAGENT_MODULE)
            agent_mode = SUB_AGENT;
#else
            fprintf(stderr, "%s: Illegal argument -X:"
		            "AgentX support not compiled in.\n", argv[0]);
            usage(argv[0]);
            exit(1);
#endif
            break;

        case 'Y':
            netsnmp_config_remember(optarg);
            break;

        default:
            usage(argv[0]);
            break;
        }
    }

    if (do_help) {
        netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, 
                               NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
        init_agent(app_name);        /* register our .conf handlers */
        init_mib_modules();
        init_snmp(app_name);
        fprintf(stderr, "Configuration directives understood:\n");
        read_config_print_usage("  ");
        exit(0);
    }

    if (optind < argc) {
#ifndef NETSNMP_NO_LISTEN_SUPPORT
        /*
         * There are optional transport addresses on the command line.  
         */
        DEBUGMSGTL(("snmpd/main", "optind %d, argc %d\n", optind, argc));
        for (i = optind; i < argc; i++) {
            char *c, *astring;
            if ((c = netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, 
					   NETSNMP_DS_AGENT_PORTS))) {
                astring = (char*)malloc(strlen(c) + 2 + strlen(argv[i]));
                if (astring == NULL) {
                    fprintf(stderr, "malloc failure processing argv[%d]\n", i);
                    exit(1);
                }
                sprintf(astring, "%s,%s", c, argv[i]);
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, 
				      NETSNMP_DS_AGENT_PORTS, astring);
                SNMP_FREE(astring);
            } else {
                netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, 
				      NETSNMP_DS_AGENT_PORTS, argv[i]);
            }
        }
        DEBUGMSGTL(("snmpd/main", "port spec: %s\n",
                    netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, 
					  NETSNMP_DS_AGENT_PORTS)));
#else /* NETSNMP_NO_LISTEN_SUPPORT */
        fprintf(stderr, "You specified ports to open; this agent was built to only send notifications\n");
        exit(1);
#endif /* NETSNMP_NO_LISTEN_SUPPORT */
    }

#ifdef NETSNMP_LOGFILE
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_FILE
    if (0 == log_set)
        snmp_enable_filelog(NETSNMP_LOGFILE,
                            netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID,
                                                   NETSNMP_DS_LIB_APPEND_LOGFILES));
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_FILE */
#endif

#ifdef USING_UTIL_FUNCS_RESTART_MODULE
    {
        /*
         * Initialize a argv set to the current for restarting the agent.
         */
        char *cptr, **argvptr;

        argvrestartp = (char **)malloc((argc + 2) * sizeof(char *));
        argvptr = argvrestartp;
        for (i = 0, ret = 1; i < argc; i++) {
            ret += strlen(argv[i]) + 1;
        }
        argvrestart = (char *) malloc(ret);
        argvrestartname = (char *) malloc(strlen(argv[0]) + 1);
        if (!argvrestartp || !argvrestart || !argvrestartname) {
            fprintf(stderr, "malloc failure processing argvrestart\n");
            exit(1);
        }
        strcpy(argvrestartname, argv[0]);

        for (cptr = argvrestart, i = 0; i < argc; i++) {
            strcpy(cptr, argv[i]);
            *(argvptr++) = cptr;
            cptr += strlen(argv[i]) + 1;
        }
    }
#endif /* USING_UTIL_FUNCS_RESTART_MODULE */

    if (agent_mode == -1) {
        if (strstr(argv[0], "agentxd") != NULL) {
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
				   NETSNMP_DS_AGENT_ROLE, SUB_AGENT);
        } else {
            netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
				   NETSNMP_DS_AGENT_ROLE, MASTER_AGENT);
        }
    } else {
        netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
			       NETSNMP_DS_AGENT_ROLE, agent_mode);
    }

    SOCK_STARTUP;
    if (init_agent(app_name) != 0) {
        snmp_log(LOG_ERR, "Agent initialization failed\n");
        exit(1);
    }
    init_mib_modules();

    /*
     * start library 
     */
    init_snmp(app_name);

    if ((ret = init_master_agent()) != 0) {
        /*
         * Some error opening one of the specified agent transports.  
         */
        snmp_log(LOG_ERR, "Server Exiting with code 1\n");
        exit(1);
    }

    /*
     * Initialize the world.  Detach from the shell.  Create initial user.  
     */
    if(!dont_fork) {
        int quit = ! netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                            NETSNMP_DS_AGENT_QUIT_IMMEDIATELY);
        ret = netsnmp_daemonize(quit,
#ifndef NETSNMP_FEATURE_REMOVE_LOGGING_STDIO
                                snmp_stderrlog_status()
#else /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */
                                0
#endif /* NETSNMP_FEATURE_REMOVE_LOGGING_STDIO */
            );
        /*
         * xxx-rks: do we care if fork fails? I think we should...
         */
        if(ret != 0) {
            snmp_log(LOG_ERR, "Server Exiting with code 1\n");
            exit(1);
        }
    }

#if HAVE_GETPID
    if (pid_file != NULL) {
        /*
         * unlink the pid_file, if it exists, prior to open.  Without
         * doing this the open will fail if the user specified pid_file
         * already exists.
         */
        unlink(pid_file);
        fd = open(pid_file, O_CREAT | O_EXCL | O_WRONLY, 0600);
        if (fd == -1) {
            snmp_log_perror(pid_file);
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
                                        NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        } else {
            if ((PID = fdopen(fd, "w")) == NULL) {
                snmp_log_perror(pid_file);
                exit(1);
            } else {
                fprintf(PID, "%d\n", (int) getpid());
                fclose(PID);
            }
#ifndef _MSC_VER
            /* The sequence open()/fdopen()/fclose()/close() makes MSVC crash,
               hence skip the close() call when using the MSVC runtime. */
            close(fd);
#endif
        }
    }
#endif

#if defined(HAVE_UNISTD_H) && (defined(HAVE_CHOWN) || defined(HAVE_SETGID) || defined(HAVE_SETUID))
    {
    const char     *persistent_dir;
    int             uid, gid;

    persistent_dir = get_persistent_directory();
    mkdirhier( persistent_dir, NETSNMP_AGENT_DIRECTORY_MODE, 0 );
   
    uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
			     NETSNMP_DS_AGENT_USERID);
    gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
			     NETSNMP_DS_AGENT_GROUPID);
    
#ifdef HAVE_CHOWN
    if ( uid != 0 || gid != 0 )
        chown( persistent_dir, uid, gid );
#endif

#ifdef HAVE_SETGID
    if ((gid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
				  NETSNMP_DS_AGENT_GROUPID)) > 0) {
        DEBUGMSGTL(("snmpd/main", "Changing gid to %d.\n", gid));
        if (setgid(gid) == -1
#ifdef HAVE_SETGROUPS
            || setgroups(1, (gid_t *)&gid) == -1
#endif
            ) {
            snmp_log_perror("setgid failed");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        }
    }
#endif
#ifdef HAVE_SETUID
    if ((uid = netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, 
				  NETSNMP_DS_AGENT_USERID)) > 0) {
#if HAVE_GETPWNAM && HAVE_PWD_H && HAVE_INITGROUPS
        struct passwd *info;

        /*
         * Set supplementary groups before changing UID
         *   (which probably involves giving up privileges)
         */
        info = getpwuid(uid);
        if (info) {
            DEBUGMSGTL(("snmpd/main", "Supplementary groups for %s.\n", info->pw_name));
            if (initgroups(info->pw_name, (gid != 0 ? (gid_t)gid : info->pw_gid)) == -1) {
                snmp_log_perror("initgroups failed");
                if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
                                            NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                    exit(1);
                }
            }
        }
        endpwent();
#endif
        DEBUGMSGTL(("snmpd/main", "Changing uid to %d.\n", uid));
        if (setuid(uid) == -1) {
            snmp_log_perror("setuid failed");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
					NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                exit(1);
            }
        }
    }
#endif
    }
#endif

    /*
     * Store persistent data immediately in case we crash later.  
     */
    snmp_store(app_name);

#ifdef SIGHUP
    DEBUGMSGTL(("signal", "registering SIGHUP signal handler\n"));
    signal(SIGHUP, SnmpdReconfig);
#endif

    /*
     * Send coldstart trap if possible.  
     */
    send_easy_trap(0, 0);

	// 控制台对接
	man_client_init(&client, &ar);
	swSpanningTree_module_init(&client, &ar);


#if 0
	int err = pthread_create(&man_thread_id, NULL, (void *)man_run, NULL);
	if (err != 0){
		 syslog(LOG_ERR, "can't create thread: %s\n", strerror(err));
		 return -1;
	}
#endif

    /*
     * We're up, log our version number.  
     */
    snmp_log(LOG_INFO, "NET-SNMP version %s\n", netsnmp_get_version());
#ifdef WIN32SERVICE
    agent_status = AGENT_RUNNING;
#endif
    netsnmp_addrcache_initialise();

    /*
     * Forever monitor the dest_port for incoming PDUs.  
     */
    DEBUGMSGTL(("snmpd/main", "We're up.  Starting to process data.\n"));
    if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
				NETSNMP_DS_AGENT_QUIT_IMMEDIATELY))
        receive();
    DEBUGMSGTL(("snmpd/main", "sending shutdown trap\n"));
    SnmpTrapNodeDown();
    DEBUGMSGTL(("snmpd/main", "Bye...\n"));
    snmp_shutdown(app_name);
    shutdown_master_agent();
    shutdown_agent();

    if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, 
				NETSNMP_DS_AGENT_LEAVE_PIDFILE) &&
	(pid_file != NULL)) {
        unlink(pid_file);
    }
#ifdef WIN32SERVICE
    agent_status = AGENT_STOPPED;
#endif

#ifdef USING_UTIL_FUNCS_RESTART_MODULE
    SNMP_FREE(argvrestartname);
    SNMP_FREE(argvrestart);
    SNMP_FREE(argvrestartp);
#endif /* USING_UTIL_FUNCS_RESTART_MODULE */

    SOCK_CLEANUP;
    return 0;
}                               /* End main() -- snmpd */
Esempio n. 9
0
static int				/* O - 0 = success, 1 = fail */
make_subpackage(const char     *prodname,
					/* I - Product short name */
                const char     *directory,
					/* I - Directory for distribution files */
                const char     *platname,
					/* I - Platform name */
                dist_t         *dist,	/* I - Distribution information */
	        struct utsname *platform,
					/* I - Platform information */
		const char     *subpackage)
					/* I - Subpackage */
{
  int			i, j;		/* Looping vars */
  const char		*header;	/* Dependency header string */
  FILE			*fp;		/* Control file */
  char			prodfull[255],	/* Full name of product */
			name[1024],	/* Full product name */
			filename[1024];	/* Destination filename */
  command_t		*c;		/* Current command */
  depend_t		*d;		/* Current dependency */
  file_t		*file;		/* Current distribution file */
  struct passwd		*pwd;		/* Pointer to user record */
  struct group		*grp;		/* Pointer to group record */
  const char		*runlevels,	/* Run levels */
			*rlptr;		/* Pointer into runlevels */
  static const char	*depends[] =	/* Dependency names */
			{
			  "Depends:",
			  "Conflicts:",
			  "Replaces:",
			  "Provides:"
			};


 /*
  * Figure out the full name of the distribution...
  */

  if (subpackage)
    snprintf(prodfull, sizeof(prodfull), "%s-%s", prodname, subpackage);
  else
    strlcpy(prodfull, prodname, sizeof(prodfull));

 /*
  * Then the subdirectory name...
  */

  if (dist->release[0])
    snprintf(name, sizeof(name), "%s-%s-%s", prodfull, dist->version,
             dist->release);
  else
    snprintf(name, sizeof(name), "%s-%s", prodfull, dist->version);

  if (platname[0])
  {
    strlcat(name, "-", sizeof(name));
    strlcat(name, platname, sizeof(name));
  }

  if (Verbosity)
    printf("Creating Debian %s distribution...\n", name);

 /*
  * Write the control file for DPKG...
  */

  if (Verbosity)
    puts("Creating control file...");

  snprintf(filename, sizeof(filename), "%s/%s", directory, name);
  mkdir(filename, 0777);
  strlcat(filename, "/DEBIAN", sizeof(filename));
  mkdir(filename, 0777);
  chmod(filename, 0755);

  strlcat(filename, "/control", sizeof(filename));

  if ((fp = fopen(filename, "w")) == NULL)
  {
    fprintf(stderr, "epm: Unable to create control file \"%s\" - %s\n", filename,
            strerror(errno));
    return (1);
  }

  fprintf(fp, "Package: %s\n", prodfull);
  if (dist->release[0])
    fprintf(fp, "Version: %s-%s\n", dist->version, dist->release);
  else
    fprintf(fp, "Version: %s\n", dist->version);
  fprintf(fp, "Maintainer: %s\n", dist->vendor);

 /*
  * The Architecture attribute needs to match the uname info
  * (which we change in get_platform to a common name)
  */

  if (!strcmp(platform->machine, "intel"))
    fputs("Architecture: i386\n", fp);
  else if (!strcmp(platform->machine, "ppc"))
    fputs("Architecture: powerpc\n", fp);
  else
    fprintf(fp, "Architecture: %s\n", platform->machine);

  fprintf(fp, "Description: %s\n", dist->product);
  fprintf(fp, " Copyright: %s\n", dist->copyright);
  for (i = 0; i < dist->num_descriptions; i ++)
    if (dist->descriptions[i].subpackage == subpackage)
      fprintf(fp, " %s\n", dist->descriptions[i].description);

  for (j = DEPEND_REQUIRES; j <= DEPEND_PROVIDES; j ++)
  {
    for (i = dist->num_depends, d = dist->depends; i > 0; i --, d ++)
      if (d->type == j && d->subpackage == subpackage)
	break;

    if (i)
    {
      for (header = depends[j]; i > 0; i --, d ++, header = ",")
	if (d->type == j && d->subpackage == subpackage)
	{
	  if (!strcmp(d->product, "_self"))
            fprintf(fp, "%s %s", header, prodname);
	  else
            fprintf(fp, "%s %s", header, d->product);

	  if (d->vernumber[0] == 0)
	  {
	    if (d->vernumber[1] < INT_MAX)
              fprintf(fp, " (<= %s)", d->version[1]);
	  }
	  else
	  {
	    if (d->vernumber[1] < INT_MAX)
	      fprintf(fp, " (>= %s, <= %s)", d->version[0], d->version[1]);
	    else
	      fprintf(fp, " (>= %s)", d->version[0]);
	  }
	}

      putc('\n', fp);
    }
  }

  fclose(fp);

 /*
  * Write the preinst file for DPKG...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_PRE_INSTALL && c->subpackage == subpackage)
      break;

  if (i)
  {
    if (Verbosity)
      puts("Creating preinst script...");

    snprintf(filename, sizeof(filename), "%s/%s/DEBIAN/preinst", directory, name);

    if ((fp = fopen(filename, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", filename,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (; i > 0; i --, c ++)
      if (c->type == COMMAND_PRE_INSTALL && c->subpackage == subpackage)
        fprintf(fp, "%s\n", c->command);

    fclose(fp);
  }

 /*
  * Write the postinst file for DPKG...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_POST_INSTALL && c->subpackage == subpackage)
      break;

  if (!i)
    for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
      if (tolower(file->type) == 'i' && file->subpackage == subpackage)
        break;

  if (i)
  {
    if (Verbosity)
      puts("Creating postinst script...");

    snprintf(filename, sizeof(filename), "%s/%s/DEBIAN/postinst", directory, name);

    if ((fp = fopen(filename, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", filename,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
      if (c->type == COMMAND_POST_INSTALL && c->subpackage == subpackage)
        fprintf(fp, "%s\n", c->command);

    for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
      if (tolower(file->type) == 'i' && file->subpackage == subpackage)
      {
        runlevels = get_runlevels(file, "02345");

        fprintf(fp, "update-rc.d %s start %02d", file->dst,
	        get_start(file, 99));

        for (rlptr = runlevels; isdigit(*rlptr & 255); rlptr ++)
	  if (*rlptr != '0')
	    fprintf(fp, " %c", *rlptr);

	if (strchr(runlevels, '0') != NULL)
          fprintf(fp, " . stop %02d 0", get_stop(file, 0));

        fputs(" . >/dev/null\n", fp);
        fprintf(fp, "/etc/init.d/%s start\n", file->dst);
      }

    fclose(fp);
  }

 /*
  * Write the prerm file for DPKG...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_PRE_REMOVE && c->subpackage == subpackage)
      break;

  if (!i)
    for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
      if (tolower(file->type) == 'i' && file->subpackage == subpackage)
        break;

  if (i)
  {
    if (Verbosity)
      puts("Creating prerm script...");

    snprintf(filename, sizeof(filename), "%s/%s/DEBIAN/prerm", directory, name);

    if ((fp = fopen(filename, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", filename,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
      if (c->type == COMMAND_PRE_REMOVE && c->subpackage == subpackage)
        fprintf(fp, "%s\n", c->command);

    for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
      if (tolower(file->type) == 'i' && file->subpackage == subpackage)
        fprintf(fp, "/etc/init.d/%s stop\n", file->dst);

    fclose(fp);
  }

 /*
  * Write the postrm file for DPKG...
  */

  for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
    if (c->type == COMMAND_POST_REMOVE && c->subpackage == subpackage)
      break;

  if (!i)
    for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
      if (tolower(file->type) == 'i' && file->subpackage == subpackage)
        break;

  if (i)
  {
    if (Verbosity)
      puts("Creating postrm script...");

    snprintf(filename, sizeof(filename), "%s/%s/DEBIAN/postrm", directory, name);

    if ((fp = fopen(filename, "w")) == NULL)
    {
      fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", filename,
              strerror(errno));
      return (1);
    }

    fchmod(fileno(fp), 0755);

    fputs("#!/bin/sh\n", fp);
    fputs("# " EPM_VERSION "\n", fp);

    for (i = dist->num_commands, c = dist->commands; i > 0; i --, c ++)
      if (c->type == COMMAND_POST_REMOVE && c->subpackage == subpackage)
	fprintf(fp, "%s\n", c->command);

    for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
      if (tolower(file->type) == 'i' && file->subpackage == subpackage)
      {
        fputs("if [ purge = \"$1\" ]; then\n", fp);
        fprintf(fp, "	update-rc.d %s remove >/dev/null\n", file->dst);
        fputs("fi\n", fp);
      }

    fclose(fp);
  }

 /*
  * Write the conffiles file for DPKG...
  */

  if (Verbosity)
    puts("Creating conffiles...");

  snprintf(filename, sizeof(filename), "%s/%s/DEBIAN/conffiles", directory, name);

  if ((fp = fopen(filename, "w")) == NULL)
  {
    fprintf(stderr, "epm: Unable to create script file \"%s\" - %s\n", filename,
            strerror(errno));
    return (1);
  }

  for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
    if (tolower(file->type) == 'c' && file->subpackage == subpackage)
      fprintf(fp, "%s\n", file->dst);
    else if (tolower(file->type) == 'i' && file->subpackage == subpackage)
      fprintf(fp, "/etc/init.d/%s\n", file->dst);

  fclose(fp);

 /*
  * Copy the files over...
  */

  if (Verbosity)
    puts("Copying temporary distribution files...");

  for (i = dist->num_files, file = dist->files; i > 0; i --, file ++)
  {
    if (file->subpackage != subpackage)
      continue;

   /*
    * Find the username and groupname IDs...
    */

    pwd = getpwnam(file->user);
    grp = getgrnam(file->group);

    endpwent();
    endgrent();

   /*
    * Copy the file or make the directory or make the symlink as needed...
    */

    switch (tolower(file->type))
    {
      case 'c' :
      case 'f' :
          snprintf(filename, sizeof(filename), "%s/%s%s", directory, name,
	           file->dst);

	  if (Verbosity > 1)
	    printf("%s -> %s...\n", file->src, filename);

	  if (copy_file(filename, file->src, file->mode, pwd ? pwd->pw_uid : 0,
			grp ? grp->gr_gid : 0))
	    return (1);
          break;
      case 'i' :
          snprintf(filename, sizeof(filename), "%s/%s/etc/init.d/%s",
	           directory, name, file->dst);

	  if (Verbosity > 1)
	    printf("%s -> %s...\n", file->src, filename);

	  if (copy_file(filename, file->src, file->mode, pwd ? pwd->pw_uid : 0,
			grp ? grp->gr_gid : 0))
	    return (1);
          break;
      case 'd' :
          snprintf(filename, sizeof(filename), "%s/%s%s", directory, name,
	           file->dst);

	  if (Verbosity > 1)
	    printf("Directory %s...\n", filename);

          make_directory(filename, file->mode, pwd ? pwd->pw_uid : 0,
			 grp ? grp->gr_gid : 0);
          break;
      case 'l' :
          snprintf(filename, sizeof(filename), "%s/%s%s", directory, name,
	           file->dst);

	  if (Verbosity > 1)
	    printf("%s -> %s...\n", file->src, filename);

          make_link(filename, file->src);
          break;
    }
  }

 /*
  * Build the distribution from the spec file...
  */

  if (Verbosity)
    printf("Building Debian %s binary distribution...\n", name);

  if (run_command(directory, "dpkg --build %s", name))
    return (1);

 /*
  * Remove temporary files...
  */

  if (!KeepFiles)
  {
    if (Verbosity)
      printf("Removing temporary %s distribution files...\n", name);

    snprintf(filename, sizeof(filename), "%s/%s", directory, name);
    unlink_directory(filename);
  }

  return (0);
}
Esempio n. 10
0
/*
 * login - create a new login session for a user
 *
 *	login is typically called by getty as the second step of a
 *	new user session. getty is responsible for setting the line
 *	characteristics to a reasonable set of values and getting
 *	the name of the user to be logged in. login may also be
 *	called to create a new user session on a pty for a variety
 *	of reasons, such as X servers or network logins.
 *
 *	the flags which login supports are
 *	
 *	-p - preserve the environment
 *	-r - perform autologin protocol for rlogin
 *	-f - do not perform authentication, user is preauthenticated
 *	-h - the name of the remote host
 */
int main (int argc, char **argv)
{
	const char *tmptty;
	char tty[BUFSIZ];

#ifdef RLOGIN
	char term[128] = "";
#endif				/* RLOGIN */
#if defined(HAVE_STRFTIME) && !defined(USE_PAM)
	char ptime[80];
#endif
	unsigned int delay;
	unsigned int retries;
	bool failed;
	bool subroot = false;
#ifndef USE_PAM
	bool is_console;
#endif
	int err;
	const char *cp;
	char *tmp;
	char fromhost[512];
	struct passwd *pwd = NULL;
	char **envp = environ;
	const char *failent_user;
	/*@null@*/struct utmp *utent;

#ifdef USE_PAM
	int retcode;
	pid_t child;
	char *pam_user = NULL;
#else
	struct spwd *spwd = NULL;
#endif
	/*
	 * Some quick initialization.
	 */

	sanitize_env ();

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	initenv ();

	amroot = (getuid () == 0);
	Prog = Basename (argv[0]);

	if (geteuid() != 0) {
		fprintf (stderr, _("%s: Cannot possibly work without effective root\n"), Prog);
		exit (1);
	}

	process_flags (argc, argv);

	if ((isatty (0) == 0) || (isatty (1) == 0) || (isatty (2) == 0)) {
		exit (1);	/* must be a terminal */
	}

	utent = get_current_utmp ();
	/*
	 * Be picky if run by normal users (possible if installed setuid
	 * root), but not if run by root. This way it still allows logins
	 * even if your getty is broken, or if something corrupts utmp,
	 * but users must "exec login" which will use the existing utmp
	 * entry (will not overwrite remote hostname).  --marekm
	 */
	if (!amroot && (NULL == utent)) {
		(void) puts (_("No utmp entry.  You must exec \"login\" from the lowest level \"sh\""));
		exit (1);
	}
	/* NOTE: utent might be NULL afterwards */

	tmptty = ttyname (0);
	if (NULL == tmptty) {
		tmptty = "UNKNOWN";
	}
	STRFCPY (tty, tmptty);

#ifndef USE_PAM
	is_console = console (tty);
#endif

	if (rflg || hflg) {
		/*
		 * Add remote hostname to the environment. I think
		 * (not sure) I saw it once on Irix.  --marekm
		 */
		addenv ("REMOTEHOST", hostname);
	}
	if (fflg) {
		preauth_flag = true;
	}
	if (hflg) {
		reason = PW_RLOGIN;
	}
#ifdef RLOGIN
	if (rflg) {
		assert (NULL == username);
		username = xmalloc (USER_NAME_MAX_LENGTH + 1);
		username[USER_NAME_MAX_LENGTH] = '\0';
		if (do_rlogin (hostname, username, USER_NAME_MAX_LENGTH, term, sizeof term)) {
			preauth_flag = true;
		} else {
			free (username);
			username = NULL;
		}
	}
#endif				/* RLOGIN */

	OPENLOG ("login");

	setup_tty ();

#ifndef USE_PAM
	(void) umask (getdef_num ("UMASK", GETDEF_DEFAULT_UMASK));

	{
		/* 
		 * Use the ULIMIT in the login.defs file, and if
		 * there isn't one, use the default value. The
		 * user may have one for themselves, but otherwise,
		 * just take what you get.
		 */
		long limit = getdef_long ("ULIMIT", -1L);

		if (limit != -1) {
			set_filesize_limit (limit);
		}
	}

#endif
	/*
	 * The entire environment will be preserved if the -p flag
	 * is used.
	 */
	if (pflg) {
		while (NULL != *envp) {	/* add inherited environment, */
			addenv (*envp, NULL); /* some variables change later */
			envp++;
		}
	}

#ifdef RLOGIN
	if (term[0] != '\0') {
		addenv ("TERM", term);
	} else
#endif				/* RLOGIN */
	{
		/* preserve TERM from getty */
		if (!pflg) {
			tmp = getenv ("TERM");
			if (NULL != tmp) {
				addenv ("TERM", tmp);
			}
		}
	}

	init_env ();

	if (optind < argc) {	/* now set command line variables */
		set_env (argc - optind, &argv[optind]);
	}

	if (rflg || hflg) {
		cp = hostname;
#ifdef	HAVE_STRUCT_UTMP_UT_HOST
	} else if ((NULL != utent) && ('\0' != utent->ut_host[0])) {
		cp = utent->ut_host;
#endif				/* HAVE_STRUCT_UTMP_UT_HOST */
	} else {
		cp = "";
	}

	if ('\0' != *cp) {
		snprintf (fromhost, sizeof fromhost,
		          " on '%.100s' from '%.200s'", tty, cp);
	} else {
		snprintf (fromhost, sizeof fromhost,
		          " on '%.100s'", tty);
	}

      top:
	/* only allow ALARM sec. for login */
	(void) signal (SIGALRM, alarm_handler);
	timeout = getdef_unum ("LOGIN_TIMEOUT", ALARM);
	if (timeout > 0) {
		(void) alarm (timeout);
	}

	environ = newenvp;	/* make new environment active */
	delay   = getdef_unum ("FAIL_DELAY", 1);
	retries = getdef_unum ("LOGIN_RETRIES", RETRIES);

#ifdef USE_PAM
	retcode = pam_start ("login", username, &conv, &pamh);
	if (retcode != PAM_SUCCESS) {
		fprintf (stderr,
		         _("login: PAM Failure, aborting: %s\n"),
		         pam_strerror (pamh, retcode));
		SYSLOG ((LOG_ERR, "Couldn't initialize PAM: %s",
		         pam_strerror (pamh, retcode)));
		exit (99);
	}

	/*
	 * hostname & tty are either set to NULL or their correct values,
	 * depending on how much we know. We also set PAM's fail delay to
	 * ours.
	 *
	 * PAM_RHOST and PAM_TTY are used for authentication, only use
	 * information coming from login or from the caller (e.g. no utmp)
	 */
	retcode = pam_set_item (pamh, PAM_RHOST, hostname);
	PAM_FAIL_CHECK;
	retcode = pam_set_item (pamh, PAM_TTY, tty);
	PAM_FAIL_CHECK;
#ifdef HAS_PAM_FAIL_DELAY
	retcode = pam_fail_delay (pamh, 1000000 * delay);
	PAM_FAIL_CHECK;
#endif
	/* if fflg, then the user has already been authenticated */
	if (!fflg) {
		unsigned int failcount = 0;
		char hostn[256];
		char loginprompt[256];	/* That's one hell of a prompt :) */

		/* Make the login prompt look like we want it */
		if (gethostname (hostn, sizeof (hostn)) == 0) {
			snprintf (loginprompt,
			          sizeof (loginprompt),
			          _("%s login: "******"login: "******"TOO MANY LOGIN TRIES (%u)%s FOR '%s'",
				         failcount, fromhost, failent_user));
				fprintf(stderr,
				        _("Maximum number of tries exceeded (%u)\n"),
				        failcount);
				PAM_END;
				exit(0);
			} else if (retcode == PAM_ABORT) {
				/* Serious problems, quit now */
				(void) fputs (_("login: abort requested by PAM\n"), stderr);
				SYSLOG ((LOG_ERR,"PAM_ABORT returned from pam_authenticate()"));
				PAM_END;
				exit(99);
			} else if (retcode != PAM_SUCCESS) {
				SYSLOG ((LOG_NOTICE,"FAILED LOGIN (%u)%s FOR '%s', %s",
				         failcount, fromhost, failent_user,
				         pam_strerror (pamh, retcode)));
				failed = true;
			}

			if (!failed) {
				break;
			}

#ifdef WITH_AUDIT
			audit_fd = audit_open ();
			audit_log_acct_message (audit_fd,
			                        AUDIT_USER_LOGIN,
			                        NULL,    /* Prog. name */
			                        "login",
			                        failent_user,
			                        AUDIT_NO_ID,
			                        hostname,
			                        NULL,    /* addr */
			                        tty,
			                        0);      /* result */
			close (audit_fd);
#endif				/* WITH_AUDIT */

			(void) puts ("");
			(void) puts (_("Login incorrect"));

			if (failcount >= retries) {
				SYSLOG ((LOG_NOTICE,
				         "TOO MANY LOGIN TRIES (%u)%s FOR '%s'",
				         failcount, fromhost, failent_user));
				fprintf(stderr,
				        _("Maximum number of tries exceeded (%u)\n"),
				        failcount);
				PAM_END;
				exit(0);
			}

			/*
			 * Let's give it another go around.
			 * Even if a username was given on the command
			 * line, prompt again for the username.
			 */
			retcode = pam_set_item (pamh, PAM_USER, NULL);
			PAM_FAIL_CHECK;
		}

		/* We don't get here unless they were authenticated above */
		(void) alarm (0);
	}

	/* Check the account validity */
	retcode = pam_acct_mgmt (pamh, 0);
	if (retcode == PAM_NEW_AUTHTOK_REQD) {
		retcode = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
	}
	PAM_FAIL_CHECK;

	/* Open the PAM session */
	get_pam_user (&pam_user);
	retcode = pam_open_session (pamh, hushed (pam_user) ? PAM_SILENT : 0);
	PAM_FAIL_CHECK;

	/* Grab the user information out of the password file for future usage
	 * First get the username that we are actually using, though.
	 *
	 * From now on, we will discard changes of the user (PAM_USER) by
	 * PAM APIs.
	 */
	get_pam_user (&pam_user);
	if (NULL != username) {
		free (username);
	}
	username = pam_user;
	failent_user = get_failent_user (username);

	pwd = xgetpwnam (username);
	if (NULL == pwd) {
		SYSLOG ((LOG_ERR, "cannot find user %s", failent_user));
		exit (1);
	}

	/* This set up the process credential (group) and initialize the
	 * supplementary group access list.
	 * This has to be done before pam_setcred
	 */
	if (setup_groups (pwd) != 0) {
		exit (1);
	}

	retcode = pam_setcred (pamh, PAM_ESTABLISH_CRED);
	PAM_FAIL_CHECK;
	/* NOTE: If pam_setcred changes PAM_USER, this will not be taken
	 * into account.
	 */

#else				/* ! USE_PAM */
	while (true) {	/* repeatedly get login/password pairs */
		/* user_passwd is always a pointer to this constant string
		 * or a passwd or shadow password that will be memzero by
		 * pw_free / spw_free.
		 * Do not free() user_passwd. */
		const char *user_passwd = "!";

		/* Do some cleanup to avoid keeping entries we do not need
		 * anymore. */
		if (NULL != pwd) {
			pw_free (pwd);
			pwd = NULL;
		}
		if (NULL != spwd) {
			spw_free (spwd);
			spwd = NULL;
		}

		failed = false;	/* haven't failed authentication yet */
		if (NULL == username) {	/* need to get a login id */
			if (subroot) {
				closelog ();
				exit (1);
			}
			preauth_flag = false;
			username = xmalloc (USER_NAME_MAX_LENGTH + 1);
			username[USER_NAME_MAX_LENGTH] = '\0';
			login_prompt (_("\n%s login: "******"!",
			 * the account is locked and the user cannot
			 * login, even if they have been
			 * "pre-authenticated."
			 */
			if (   ('!' == user_passwd[0])
			    || ('*' == user_passwd[0])) {
				failed = true;
			}
		}

		if (strcmp (user_passwd, SHADOW_PASSWD_STRING) == 0) {
			spwd = xgetspnam (username);
			if (NULL != spwd) {
				user_passwd = spwd->sp_pwdp;
			} else {
				/* The user exists in passwd, but not in
				 * shadow. SHADOW_PASSWD_STRING indicates
				 * that the password shall be in shadow.
				 */
				SYSLOG ((LOG_WARN,
				         "no shadow password for '%s'%s",
				         username, fromhost));
			}
		}

		/*
		 * The -r and -f flags provide a name which has already
		 * been authenticated by some server.
		 */
		if (preauth_flag) {
			goto auth_ok;
		}

		if (pw_auth (user_passwd, username, reason, (char *) 0) == 0) {
			goto auth_ok;
		}

		SYSLOG ((LOG_WARN, "invalid password for '%s' %s",
		         failent_user, fromhost));
		failed = true;

	      auth_ok:
		/*
		 * This is the point where all authenticated users wind up.
		 * If you reach this far, your password has been
		 * authenticated and so on.
		 */
		if (   !failed
		    && (NULL != pwd)
		    && (0 == pwd->pw_uid)
		    && !is_console) {
			SYSLOG ((LOG_CRIT, "ILLEGAL ROOT LOGIN %s", fromhost));
			failed = true;
		}
		if (   !failed
		    && !login_access (username, ('\0' != *hostname) ? hostname : tty)) {
			SYSLOG ((LOG_WARN, "LOGIN '%s' REFUSED %s",
			         username, fromhost));
			failed = true;
		}
		if (   (NULL != pwd)
		    && getdef_bool ("FAILLOG_ENAB")
		    && !failcheck (pwd->pw_uid, &faillog, failed)) {
			SYSLOG ((LOG_CRIT,
			         "exceeded failure limit for '%s' %s",
			         username, fromhost));
			failed = true;
		}
		if (!failed) {
			break;
		}

		/* don't log non-existent users */
		if ((NULL != pwd) && getdef_bool ("FAILLOG_ENAB")) {
			failure (pwd->pw_uid, tty, &faillog);
		}
		if (getdef_str ("FTMP_FILE") != NULL) {
#ifdef USE_UTMPX
			struct utmpx *failent =
				prepare_utmpx (failent_user,
				               tty,
			/* FIXME: or fromhost? */hostname,
				               utent);
#else				/* !USE_UTMPX */
			struct utmp *failent =
				prepare_utmp (failent_user,
				              tty,
				              hostname,
				              utent);
#endif				/* !USE_UTMPX */
			failtmp (failent_user, failent);
			free (failent);
		}

		retries--;
		if (retries <= 0) {
			SYSLOG ((LOG_CRIT, "REPEATED login failures%s",
			         fromhost));
		}

		/*
		 * If this was a passwordless account and we get here, login
		 * was denied (securetty, faillog, etc.). There was no
		 * password prompt, so do it now (will always fail - the bad
		 * guys won't see that the passwordless account exists at
		 * all).  --marekm
		 */
		if (user_passwd[0] == '\0') {
			pw_auth ("!", username, reason, (char *) 0);
		}

		/*
		 * Authentication of this user failed.
		 * The username must be confirmed in the next try.
		 */
		free (username);
		username = NULL;

		/*
		 * Wait a while (a la SVR4 /usr/bin/login) before attempting
		 * to login the user again. If the earlier alarm occurs
		 * before the sleep() below completes, login will exit.
		 */
		if (delay > 0) {
			(void) sleep (delay);
		}

		(void) puts (_("Login incorrect"));

		/* allow only one attempt with -r or -f */
		if (rflg || fflg || (retries <= 0)) {
			closelog ();
			exit (1);
		}
	}			/* while (true) */
#endif				/* ! USE_PAM */
	assert (NULL != username);
	assert (NULL != pwd);

	(void) alarm (0);		/* turn off alarm clock */

#ifndef USE_PAM			/* PAM does this */
	/*
	 * porttime checks moved here, after the user has been
	 * authenticated. now prints a message, as suggested
	 * by Ivan Nejgebauer <*****@*****.**>.  --marekm
	 */
	if (   getdef_bool ("PORTTIME_CHECKS_ENAB")
	    && !isttytime (username, tty, time ((time_t *) 0))) {
		SYSLOG ((LOG_WARN, "invalid login time for '%s'%s",
		         username, fromhost));
		closelog ();
		bad_time_notify ();
		exit (1);
	}

	check_nologin (pwd->pw_uid == 0);
#endif

	if (getenv ("IFS")) {	/* don't export user IFS ... */
		addenv ("IFS= \t\n", NULL);	/* ... instead, set a safe IFS */
	}

	if (pwd->pw_shell[0] == '*') {	/* subsystem root */
		pwd->pw_shell++;	/* skip the '*' */
		subsystem (pwd);	/* figure out what to execute */
		subroot = true;	/* say I was here again */
		endpwent ();	/* close all of the file which were */
		endgrent ();	/* open in the original rooted file */
		endspent ();	/* system. they will be re-opened */
#ifdef	SHADOWGRP
		endsgent ();	/* in the new rooted file system */
#endif
		goto top;	/* go do all this all over again */
	}

#ifdef WITH_AUDIT
	audit_fd = audit_open ();
	audit_log_acct_message (audit_fd,
	                        AUDIT_USER_LOGIN,
	                        NULL,    /* Prog. name */
	                        "login",
	                        username,
	                        AUDIT_NO_ID,
	                        hostname,
	                        NULL,    /* addr */
	                        tty,
	                        1);      /* result */
	close (audit_fd);
#endif				/* WITH_AUDIT */

#ifndef USE_PAM			/* pam_lastlog handles this */
	if (getdef_bool ("LASTLOG_ENAB")) {	/* give last login and log this one */
		dolastlog (&ll, pwd, tty, hostname);
	}
#endif

#ifndef USE_PAM			/* PAM handles this as well */
	/*
	 * Have to do this while we still have root privileges, otherwise we
	 * don't have access to /etc/shadow.
	 */
	if (NULL != spwd) {		/* check for age of password */
		if (expire (pwd, spwd)) {
			/* The user updated her password, get the new
			 * entries.
			 * Use the x variants because we need to keep the
			 * entry for a long time, and there might be other
			 * getxxyy in between.
			 */
			pw_free (pwd);
			pwd = xgetpwnam (username);
			if (NULL == pwd) {
				SYSLOG ((LOG_ERR,
				         "cannot find user %s after update of expired password",
				         username));
				exit (1);
			}
			spw_free (spwd);
			spwd = xgetspnam (username);
		}
	}
	setup_limits (pwd);	/* nice, ulimit etc. */
#endif				/* ! USE_PAM */
	chown_tty (pwd);

#ifdef USE_PAM
	/*
	 * We must fork before setuid() because we need to call
	 * pam_close_session() as root.
	 */
	(void) signal (SIGINT, SIG_IGN);
	child = fork ();
	if (child < 0) {
		/* error in fork() */
		fprintf (stderr, _("%s: failure forking: %s"),
		         Prog, strerror (errno));
		PAM_END;
		exit (0);
	} else if (child != 0) {
		/*
		 * parent - wait for child to finish, then cleanup
		 * session
		 */
		wait (NULL);
		PAM_END;
		exit (0);
	}
	/* child */
#endif

	/* If we were init, we need to start a new session */
	if (getppid() == 1) {
		setsid();
		if (ioctl(0, TIOCSCTTY, 1) != 0) {
			fprintf (stderr, _("TIOCSCTTY failed on %s"), tty);
		}
	}

	/*
	 * The utmp entry needs to be updated to indicate the new status
	 * of the session, the new PID and SID.
	 */
	update_utmp (username, tty, hostname, utent);

	/* The pwd and spwd entries for the user have been copied.
	 *
	 * Close all the files so that unauthorized access won't occur.
	 */
	endpwent ();		/* stop access to password file */
	endgrent ();		/* stop access to group file */
	endspent ();		/* stop access to shadow passwd file */
#ifdef	SHADOWGRP
	endsgent ();		/* stop access to shadow group file */
#endif

	/* Drop root privileges */
#ifndef USE_PAM
	if (setup_uid_gid (pwd, is_console))
#else
	/* The group privileges were already dropped.
	 * See setup_groups() above.
	 */
	if (change_uid (pwd))
#endif
	{
		exit (1);
	}

	setup_env (pwd);	/* set env vars, cd to the home dir */

#ifdef USE_PAM
	{
		const char *const *env;

		env = (const char *const *) pam_getenvlist (pamh);
		while ((NULL != env) && (NULL != *env)) {
			addenv (*env, NULL);
			env++;
		}
	}
#endif

	(void) setlocale (LC_ALL, "");
	(void) bindtextdomain (PACKAGE, LOCALEDIR);
	(void) textdomain (PACKAGE);

	if (!hushed (username)) {
		addenv ("HUSHLOGIN=FALSE", NULL);
		/*
		 * pam_unix, pam_mail and pam_lastlog should take care of
		 * this
		 */
#ifndef USE_PAM
		motd ();	/* print the message of the day */
		if (   getdef_bool ("FAILLOG_ENAB")
		    && (0 != faillog.fail_cnt)) {
			failprint (&faillog);
			/* Reset the lockout times if logged in */
			if (   (0 != faillog.fail_max)
			    && (faillog.fail_cnt >= faillog.fail_max)) {
				(void) puts (_("Warning: login re-enabled after temporary lockout."));
				SYSLOG ((LOG_WARN,
				         "login '%s' re-enabled after temporary lockout (%d failures)",
				         username, (int) faillog.fail_cnt));
			}
		}
		if (   getdef_bool ("LASTLOG_ENAB")
		    && (ll.ll_time != 0)) {
			time_t ll_time = ll.ll_time;

#ifdef HAVE_STRFTIME
			(void) strftime (ptime, sizeof (ptime),
			                 "%a %b %e %H:%M:%S %z %Y",
			                 localtime (&ll_time));
			printf (_("Last login: %s on %s"),
			        ptime, ll.ll_line);
#else
			printf (_("Last login: %.19s on %s"),
			        ctime (&ll_time), ll.ll_line);
#endif
#ifdef HAVE_LL_HOST		/* __linux__ || SUN4 */
			if ('\0' != ll.ll_host[0]) {
				printf (_(" from %.*s"),
				        (int) sizeof ll.ll_host, ll.ll_host);
			}
#endif
			printf (".\n");
		}
		agecheck (spwd);

		mailcheck ();	/* report on the status of mail */
#endif				/* !USE_PAM */
	} else {
		addenv ("HUSHLOGIN=TRUE", NULL);
	}

	ttytype (tty);

	(void) signal (SIGQUIT, SIG_DFL);	/* default quit signal */
	(void) signal (SIGTERM, SIG_DFL);	/* default terminate signal */
	(void) signal (SIGALRM, SIG_DFL);	/* default alarm signal */
	(void) signal (SIGHUP, SIG_DFL);	/* added this.  --marekm */
	(void) signal (SIGINT, SIG_DFL);	/* default interrupt signal */

	if (0 == pwd->pw_uid) {
		SYSLOG ((LOG_NOTICE, "ROOT LOGIN %s", fromhost));
	} else if (getdef_bool ("LOG_OK_LOGINS")) {
		SYSLOG ((LOG_INFO, "'%s' logged in %s", username, fromhost));
	}
	closelog ();
	tmp = getdef_str ("FAKE_SHELL");
	if (NULL != tmp) {
		err = shell (tmp, pwd->pw_shell, newenvp); /* fake shell */
	} else {
		/* exec the shell finally */
		err = shell (pwd->pw_shell, (char *) 0, newenvp);
	}

	return ((err == ENOENT) ? E_CMD_NOTFOUND : E_CMD_NOEXEC);
}
Esempio n. 11
0
fsnode *
read_mtree(const char *fname, fsnode *node)
{
	struct mtree_fileinfo *fi;
	FILE *fp;
	int c, error;

	/* We do not yet support nesting... */
	assert(node == NULL);

	if (strcmp(fname, "-") == 0)
		fp = stdin;
	else {
		fp = fopen(fname, "r");
		if (fp == NULL)
			err(1, "Can't open `%s'", fname);
	}

	error = mtree_file_push(fname, fp);
	if (error)
		goto out;

	bzero(&mtree_global, sizeof(mtree_global));
	bzero(&mtree_global_inode, sizeof(mtree_global_inode));
	mtree_global.inode = &mtree_global_inode;
	mtree_global_inode.nlink = 1;
	mtree_global_inode.st.st_nlink = 1;
	mtree_global_inode.st.st_atime = mtree_global_inode.st.st_ctime =
	    mtree_global_inode.st.st_mtime = time(NULL);
	errors = warnings = 0;

	setgroupent(1);
	setpassent(1);

	mtree_root = node;
	mtree_current = node;
	do {
		/* Start of a new line... */
		fi = SLIST_FIRST(&mtree_fileinfo);
		fi->line++;

		error = skip_over(fp, " \t");
		if (error)
			break;

		c = getc(fp);
		if (c == EOF) {
			error = ferror(fp) ? errno : -1;
			break;
		}

		switch (c) {
		case '\n':		/* empty line */
			error = 0;
			break;
		case '#':		/* comment -- skip to end of line. */
			error = skip_to(fp, "\n");
			if (!error)
				(void)getc(fp);
			break;
		case '/':		/* special commands */
			error = read_mtree_command(fp);
			break;
		default:		/* specification */
			ungetc(c, fp);
			error = read_mtree_spec(fp);
			break;
		}
	} while (!error);

	endpwent();
	endgrent();

	if (error <= 0 && (errors || warnings)) {
		warnx("%u error(s) and %u warning(s) in mtree manifest",
		    errors, warnings);
		if (errors)
			exit(1);
	}

 out:
	if (error > 0)
		errc(1, error, "Error reading mtree file");

	if (fp != stdin)
		fclose(fp);

	if (mtree_root != NULL)
		return (mtree_root);

	/* Handle empty specifications. */
	node = create_node(".", S_IFDIR, NULL, &mtree_global);
	node->first = node;
	return (node);
}
Esempio n. 12
0
//------------------------------------------------------------------------------
// FUNCTION: checkAccess
//
// REMARKS: Status of context user
//
// PARAMETERS:    [IN]  filename  -> file name to verify access    
//                [IN]  chkoper   -> valid options: SEC_OPT_READ,
//											  		SEC_OPT_WRITE,
//											  		SEC_OPT_READ_WRITE or
//											  		SEC_OPT_EXECUTE
//
// RETURN: TRUE, if user have privileges, otherwise FALSE
//------------------------------------------------------------------------------
Boolean
NTPProviderSecurity::checkAccess(const String filename,
                           const String chkoper) 
{
    FILE *fp;
    struct passwd *pwd;
    struct group *grp;
    struct stat st;
    int ps,	opt, i, j,
    	ct = 0, ngr = 0;
    ushort rt, gr, ot,
    	   trt, tgr;
    Boolean ok = false,
    		isRoot = false,
   		    okUser = (secUsername.size() > 0);
    char buffer[500];
    char *member;
    // Groups array
    Array<gid_t> grps;
    // store user id
	uid_t user_id = -1; 
	// store group id  - is there only one group id?
	gid_t group_id;
    int accessrights;
    String strTmp;
    String path;
    String strValue;
    Array<String> strCmd;
    Array<String> strMembers;
    
    if(okUser) {
	    // Retrieve uid from user
	    strValue.clear();
        // Go through password entries and find the entry that matches "secUsername"
	    pwd = getpwent();
	    if(pwd != NULL) {
	    	strValue.assign(pwd->pw_name);
	    	while(!String::equalNoCase(strValue, secUsername)) {
	            pwd = getpwent();
	            if(pwd == NULL)
	                break;
	            strValue.assign(pwd->pw_name);
	        }
	    }
		// indicate that the processing of the password database is complete
        endpwent();

        // If we didn't find the entry - just return
        if(strValue.size() == 0 || !String::equalNoCase(strValue, secUsername))
            return ok;

		// DLH set the group and user id
		user_id = pwd->pw_uid;
		group_id = pwd->pw_gid;
        grps.clear();
        isRoot = (user_id == 0);
    
	    if(!isRoot) {
            grps.append(group_id);

		    // Find the groups to which this user belongs and store the list in "member"
			strValue.clear(); 
		    // Return a pointer to the first group structure in the group database
		    grp = getgrent();
		    while(grp) {
				i = 0;
		    	strMembers.clear();
				member = grp->gr_mem[i++];
				while (member) {
		        	strMembers.append(member);
		        	member = grp->gr_mem[i++];
		        }
		        for(i=0; i < strMembers.size(); i++) {
		        	strValue.assign(strMembers[i]);
		        	ps = strValue.find(secUsername);
		        	if(ps >= 0) {
                        grps.append(grp->gr_gid);
		            	break;
		            }
		        }
	            // Get the next group structure
		        grp = getgrent();
		    }
	        // Indicate that the processing of the group database is complete
		    endgrent();
        }
    }
    
	// Build the command with path of file
    strCmd.clear();
    ps = filename.reverseFind('/');
    if(ps > 0) {
	    path.assign(filename.subString(0, ps));
	    strCmd.append(path);
    }
    
    // Build the command to retrieve user informations
    strCmd.append(filename);

    //
    // Identify the type test
    //    
    opt = 0;
    if(String::equalNoCase(chkoper, SEC_OPT_READ) ||
       String::equalNoCase(chkoper, SEC_OPT_READ_WRITE))
        opt = 1;
    else if(String::equalNoCase(chkoper, SEC_OPT_WRITE) ||
            String::equalNoCase(chkoper, SEC_OPT_READ_WRITE)) 
        opt = 2;
    else if(String::equalNoCase(chkoper, SEC_OPT_EXECUTE) ||
           String::equalNoCase(chkoper, SEC_OPT_ALL))
        opt = 3;
    
    // Verify permissions from directory and file name
    for(int i=0; i<strCmd.size(); i++) {
    	ok = false;
    	strTmp.assign(strCmd[i]);

       	// The stat call gets information about the file access permissions
       	if(stat(strTmp.getCString(), &st) == -1)
        	return ok;

		// Return ok, if is invalid user_id and other permission or is root
		if(!okUser && st.st_basemode & 0x04 || isRoot) 
            ok = true;
		else if(user_id > 0) 
        {            
			// Use getaccess to check permission instead of stat so that we get consistent response from OS
			accessrights = getaccess( strTmp.getCString(), user_id, grps.size(), grps.getData(),(void *) 0,(void *) 0);
        	if ( accessrights == -1) 
			// if error - just return with ok set to false
				return ok;
			
	        // Verify status by type test
	        switch(opt) {
	            case 1:
	                ok = (accessrights & R_OK);
	            	break;
	            case 2:
	                ok = (accessrights & W_OK);
	            	break;
	            case 3:
	                ok = (accessrights & X_OK);
	            	break;
	            default:
	                break;
	        }
        }
        if(!ok)
            break;
    }
    return ok;    
}
Esempio n. 13
0
File: tincd.c Progetto: seehuhn/tinc
static bool drop_privs() {
#ifdef HAVE_MINGW

	if(switchuser) {
		logger(LOG_ERR, "%s not supported on this platform", "-U");
		return false;
	}

	if(do_chroot) {
		logger(LOG_ERR, "%s not supported on this platform", "-R");
		return false;
	}

#else
	uid_t uid = 0;

	if(switchuser) {
		struct passwd *pw = getpwnam(switchuser);

		if(!pw) {
			logger(LOG_ERR, "unknown user `%s'", switchuser);
			return false;
		}

		uid = pw->pw_uid;

		if(initgroups(switchuser, pw->pw_gid) != 0 ||
						setgid(pw->pw_gid) != 0) {
			logger(LOG_ERR, "System call `%s' failed: %s",
				   "initgroups", strerror(errno));
			return false;
		}

#ifndef ANDROID
// Not supported in android NDK
		endgrent();
		endpwent();
#endif
	}

	if(do_chroot) {
		tzset();        /* for proper timestamps in logs */

		if(chroot(confbase) != 0 || chdir("/") != 0) {
			logger(LOG_ERR, "System call `%s' failed: %s",
				   "chroot", strerror(errno));
			return false;
		}

		free(confbase);
		confbase = xstrdup("");
	}

	if(switchuser)
		if(setuid(uid) != 0) {
			logger(LOG_ERR, "System call `%s' failed: %s",
				   "setuid", strerror(errno));
			return false;
		}

#endif
	return true;
}
Esempio n. 14
0
File: main.c Progetto: CoiLock/uhub
int drop_privileges()
{
	struct group* perm_group = 0;
	struct passwd* perm_user = 0;
	gid_t perm_gid = 0;
	uid_t perm_uid = 0;
	int gid_ok = 0;
	int ret = 0;

	if (arg_gid)
	{
		ret = 0;
		while ((perm_group = getgrent()) != NULL)
		{
			if (strcmp(perm_group->gr_name, arg_gid) == 0)
			{
				perm_gid = perm_group->gr_gid;
				ret = 1;
				break;
			}
		}

		endgrent();

		if (!ret)
		{
			LOG_FATAL("Unable to determine group id, check group name.");
			return -1;
		}

		LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
		ret = setgid(perm_gid);
		if (ret == -1)
		{
			LOG_FATAL("Unable to change group id, permission denied.");
			return -1;
		}
		gid_ok = 1;
	}

	if (arg_uid)
	{
		ret = 0;
		while ((perm_user = getpwent()) != NULL)
		{
			if (strcmp(perm_user->pw_name, arg_uid) == 0)
			{
				perm_uid = perm_user->pw_uid;
				if (!gid_ok)
					perm_gid = perm_user->pw_gid;
				ret = 1;
				break;
			}
		}

		endpwent();

		if (!ret)
		{
			LOG_FATAL("Unable to determine user id, check user name.");
			return -1;
		}

		if (!gid_ok) {
			LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
			ret = setgid(perm_gid);
			if (ret == -1)
			{
				LOG_FATAL("Unable to change group id, permission denied.");
				return -1;
			}
		}

		LOG_TRACE("Setting user id %d (%s)", (int) perm_uid, arg_uid);
		ret = setuid(perm_uid);
		if (ret == -1)
		{
			LOG_FATAL("Unable to change user id, permission denied.");
			return -1;
		}
	}

	return 0;
}
Esempio n. 15
0
static void listGroupsForUser(const char *name, gid_t gid, uint maxCount, Func handleNextGroup)
{
    if (Q_UNLIKELY(maxCount == 0)) {
        return;
    }
    uint found = 0;
#if HAVE_GETGROUPLIST
    QVarLengthArray<gid_t, 100> gid_buffer;
    gid_buffer.resize(100);
    int numGroups = gid_buffer.size();
    int result = getgrouplist(name, gid, gid_buffer.data(), &numGroups);
    if (result < 0 && uint(numGroups) < maxCount) {
        // getgrouplist returns -1 if the buffer was too small to store all entries, the required size is in numGroups
        qDebug("Buffer was too small: %d, need %d", gid_buffer.size(), numGroups);
        gid_buffer.resize(numGroups);
        numGroups = gid_buffer.size();
        getgrouplist(name, gid, gid_buffer.data(), &numGroups);
    }
    for (int i = 0; i < numGroups && found < maxCount; ++i) {
        struct group *g = getgrgid(gid_buffer[i]);
        // should never be null, but better be safe than crash
        if (g) {
            found++;
            handleNextGroup(g);
        }
    }
#else
    // fall back to getgrent() and reading gr->gr_mem
    // This is slower than getgrouplist, but works as well
    // add the current gid, this is often not part of g->gr_mem (e.g. build.kde.org or my openSuSE 13.1 system)
    struct group *g = getgrgid(gid);
    if (g) {
        handleNextGroup(g);
        found++;
        if (found >= maxCount) {
            return;
        }
    }

    static const auto groupContainsUser = [](struct group * g, const char *name) -> bool {
        for (char **user = g->gr_mem; *user; user++)
        {
            if (strcmp(name, *user) == 0) {
                return true;
            }
        }
        return false;
    };

    setgrent();
    while ((g = getgrent())) {
        // don't add the current gid again
        if (g->gr_gid != gid && groupContainsUser(g, name)) {
            handleNextGroup(g);
            found++;
            if (found >= maxCount) {
                break;
            }
        }
    }
    endgrent();
#endif
}
Esempio n. 16
0
/* drops privileges */
int drop_privileges(char *user, char *group){
	uid_t uid=-1;
	gid_t gid=-1;
	struct group *grp;
	struct passwd *pw;

	/* set effective group ID */
	if(group!=NULL){
		
		/* see if this is a group name */
		if(strspn(group,"0123456789")<strlen(group)){
			grp=(struct group *)getgrnam(group);
			if(grp!=NULL)
				gid=(gid_t)(grp->gr_gid);
			else
				syslog(LOG_ERR,"Warning: Could not get group entry for '%s'",group);
			endgrent();
		        }

		/* else we were passed the GID */
		else
			gid=(gid_t)atoi(group);

		/* set effective group ID if other than current EGID */
		if(gid!=getegid()){

			if(setgid(gid)==-1)
				syslog(LOG_ERR,"Warning: Could not set effective GID=%d",(int)gid);
		        }
	        }


	/* set effective user ID */
	if(user!=NULL){
		
		/* see if this is a user name */
		if(strspn(user,"0123456789")<strlen(user)){
			pw=(struct passwd *)getpwnam(user);
			if(pw!=NULL)
				uid=(uid_t)(pw->pw_uid);
			else
				syslog(LOG_ERR,"Warning: Could not get passwd entry for '%s'",user);
			endpwent();
		        }

		/* else we were passed the UID */
		else
			uid=(uid_t)atoi(user);
			
		/* set effective user ID if other than current EUID */
		if(uid!=geteuid()){

#ifdef HAVE_INITGROUPS
			/* initialize supplementary groups */
			if(initgroups(user,gid)==-1){
				if(errno==EPERM)
					syslog(LOG_ERR,"Warning: Unable to change supplementary groups using initgroups()");
				else{
					syslog(LOG_ERR,"Warning: Possibly root user failed dropping privileges with initgroups()");
					return ERROR;
			                }
	                        }
#endif

			if(setuid(uid)==-1)
				syslog(LOG_ERR,"Warning: Could not set effective UID=%d",(int)uid);
		        }
	        }

	return OK;
        }
Esempio n. 17
0
void
slap_init_user( char *user, char *group )
{
    uid_t	uid = 0;
    gid_t	gid = 0;
    int		got_uid = 0, got_gid = 0;

    if ( user ) {
	struct passwd *pwd;
	if ( isdigit( (unsigned char) *user ) ) {
	    unsigned u;

	    got_uid = 1;
	    if ( lutil_atou( &u, user ) != 0 ) {
		Debug( LDAP_DEBUG_ANY, "Unble to parse user %s\n",
		       user, 0, 0 );

		exit( EXIT_FAILURE );
	    }
	    uid = (uid_t)u;
#ifdef HAVE_GETPWUID
	    pwd = getpwuid( uid );
	    goto did_getpw;
#else
	    free( user );
	    user = NULL;
#endif
	} else {
	    pwd = getpwnam( user );
	did_getpw:
	    if ( pwd == NULL ) {
		Debug( LDAP_DEBUG_ANY, "No passwd entry for user %s\n",
		       user, 0, 0 );

		exit( EXIT_FAILURE );
	    }
	    if ( got_uid ) {
		free( user );
		user = (pwd != NULL ? ch_strdup( pwd->pw_name ) : NULL);
	    } else {
		got_uid = 1;
		uid = pwd->pw_uid;
	    }
	    got_gid = 1;
	    gid = pwd->pw_gid;
#ifdef HAVE_ENDPWENT
	    endpwent();
#endif
	}
    }

    if ( group ) {
	struct group *grp;
	if ( isdigit( (unsigned char) *group )) {
	    unsigned g;

	    if ( lutil_atou( &g, group ) != 0 ) {
		Debug( LDAP_DEBUG_ANY, "Unble to parse group %s\n",
		       group, 0, 0 );

		exit( EXIT_FAILURE );
	    }
	    gid = (uid_t)g;
#ifdef HAVE_GETGRGID
	    grp = getgrgid( gid );
	    goto did_group;
#endif
	} else {
	    grp = getgrnam( group );
	    if ( grp != NULL )
		gid = grp->gr_gid;
	did_group:
	    if ( grp == NULL ) {
		Debug( LDAP_DEBUG_ANY, "No group entry for group %s\n",
		       group, 0, 0 );

		exit( EXIT_FAILURE );
	    }
	}
	free( group );
	got_gid = 1;
    }

    if ( user ) {
	if ( getuid() == 0 && initgroups( user, gid ) != 0 ) {
	    Debug( LDAP_DEBUG_ANY,
		   "Could not set the group access (gid) list\n", 0, 0, 0 );

	    exit( EXIT_FAILURE );
	}
	free( user );
    }

#ifdef HAVE_ENDGRENT
    endgrent();
#endif

    if ( got_gid ) {
	if ( setgid( gid ) != 0 ) {
	    Debug( LDAP_DEBUG_ANY, "Could not set real group id to %d\n",
		       (int) gid, 0, 0 );

	    exit( EXIT_FAILURE );
	}
#ifdef HAVE_SETEGID
	if ( setegid( gid ) != 0 ) {
	    Debug( LDAP_DEBUG_ANY, "Could not set effective group id to %d\n",
		       (int) gid, 0, 0 );

	    exit( EXIT_FAILURE );
	}
#endif
    }

    if ( got_uid ) {
	if ( setuid( uid ) != 0 ) {
	    Debug( LDAP_DEBUG_ANY, "Could not set real user id to %d\n",
		       (int) uid, 0, 0 );

	    exit( EXIT_FAILURE );
	}
#ifdef HAVE_SETEUID
	if ( seteuid( uid ) != 0 ) {
	    Debug( LDAP_DEBUG_ANY, "Could not set effective user id to %d\n",
		       (int) uid, 0, 0 );

	    exit( EXIT_FAILURE );
	}
#endif
    }
}
Esempio n. 18
0
/*
 * process_flags - perform command line argument setting
 *
 *	process_flags() interprets the command line arguments and sets the
 *	values that the user will be created with accordingly. The values
 *	are checked for sanity.
 */
static void process_flags (int argc, char **argv)
{
	const struct group *grp;
	const struct passwd *pwd;

	const struct spwd *spwd = NULL;
	int anyflag = 0;
	int arg;

	if (argc == 1 || argv[argc - 1][0] == '-')
		usage ();

	if (!(pwd = getpwnam (argv[argc - 1]))) {
		fprintf (stderr, _("%s: user %s does not exist\n"),
			 Prog, argv[argc - 1]);
		exit (E_NOTFOUND);
	}

	user_name = argv[argc - 1];
	user_id = pwd->pw_uid;
	user_gid = pwd->pw_gid;
	user_comment = xstrdup (pwd->pw_gecos);
	user_home = xstrdup (pwd->pw_dir);
	user_shell = xstrdup (pwd->pw_shell);
#ifdef WITH_AUDIT
	user_newname = user_name;
	user_newid = user_id;
	user_newgid = user_gid;
	user_newcomment = user_comment;
	user_newhome = user_home;
	user_newshell = user_shell;
#endif

#ifdef	USE_NIS
	/*
	 * Now make sure it isn't an NIS user.
	 */
	if (__ispwNIS ()) {
		char *nis_domain;
		char *nis_master;

		fprintf (stderr, _("%s: user %s is a NIS user\n"),
			 Prog, user_name);

		if (!yp_get_default_domain (&nis_domain) &&
		    !yp_master (nis_domain, "passwd.byname", &nis_master)) {
			fprintf (stderr, _("%s: %s is the NIS master\n"),
				 Prog, nis_master);
		}
		exit (E_NOTFOUND);
	}
#endif

	if (is_shadow_pwd && (spwd = getspnam (user_name))) {
		user_expire = spwd->sp_expire;
		user_inactive = spwd->sp_inact;
#ifdef WITH_AUDIT
		user_newexpire = user_expire;
		user_newinactive = user_inactive;
#endif
	}

	{
		/*
		 * Parse the command line options.
		 */
		int c;
		static struct option long_options[] = {
			{"append", required_argument, NULL, 'a'},
			{"comment", required_argument, NULL, 'c'},
			{"home", required_argument, NULL, 'd'},
			{"expiredate", required_argument, NULL, 'e'},
			{"inactive", required_argument, NULL, 'f'},
			{"gid", required_argument, NULL, 'g'},
			{"groups", required_argument, NULL, 'G'},
			{"help", no_argument, NULL, 'h'},
			{"login", required_argument, NULL, 'l'},
			{"lock", no_argument, NULL, 'L'},
			{"move-home", no_argument, NULL, 'm'},
			{"non-unique", no_argument, NULL, 'o'},
			{"password", required_argument, NULL, 'p'},
			{"shell", required_argument, NULL, 's'},
			{"uid", required_argument, NULL, 'u'},
			{"unlock", no_argument, NULL, 'U'},
			{NULL, 0, NULL, '\0'}
		};
		while ((c =
			getopt_long (argc, argv, "ac:d:e:f:g:G:l:Lmop:s:u:U",
				     long_options, NULL)) != -1) {
			switch (c) {
			case 'a':
				aflg++;
				break;
			case 'c':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
#ifdef WITH_AUDIT
				user_newcomment = optarg;
#else
				user_comment = optarg;
#endif
				cflg++;
				break;
			case 'd':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
				dflg++;
				user_newhome = optarg;
				break;
			case 'e':
				if (*optarg) {
#ifdef WITH_AUDIT
					user_newexpire = strtoday (optarg);
					if (user_newexpire == -1) {
#else
					user_expire = strtoday (optarg);
					if (user_expire == -1) {
#endif
						fprintf (stderr,
							 _
							 ("%s: invalid date `%s'\n"),
							 Prog, optarg);
						exit (E_BAD_ARG);
					}
#ifdef WITH_AUDIT
					user_newexpire *= DAY / SCALE;
#else
					user_expire *= DAY / SCALE;
#endif
				} else
#ifdef WITH_AUDIT
					user_newexpire = -1;
#else
					user_expire = -1;
#endif
				eflg++;
				break;
			case 'f':
#ifdef WITH_AUDIT
				user_newinactive = get_number (optarg);
#else
				user_inactive = get_number (optarg);
#endif
				fflg++;
				break;
			case 'g':
				grp = getgr_nam_gid (optarg);
				if (!grp) {
					fprintf (stderr,
						 _("%s: unknown group %s\n"),
						 Prog, optarg);
					exit (E_NOTFOUND);
				}
				user_newgid = grp->gr_gid;
				gflg++;
				break;
			case 'G':
				if (get_groups (optarg))
					exit (E_NOTFOUND);
				Gflg++;
				break;
			case 'l':
				if (!check_user_name (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}

				/*
				 * If the name does not really change, we mustn't
				 * set the flag as this will cause rather serious
				 * problems later!
				 */
				if (strcmp (user_name, optarg))
					lflg++;

				user_newname = optarg;
				break;
			case 'L':
				if (Uflg || pflg)
					usage ();

				Lflg++;
				break;
			case 'm':
				if (!dflg)
					usage ();

				mflg++;
				break;
			case 'o':
				if (!uflg)
					usage ();

				oflg++;
				break;
			case 'p':
				if (Lflg || Uflg)
					usage ();

				user_pass = optarg;
				pflg++;
				break;
			case 's':
				if (!VALID (optarg)) {
					fprintf (stderr,
						 _("%s: invalid field `%s'\n"),
						 Prog, optarg);
					exit (E_BAD_ARG);
				}
#ifdef WITH_AUDIT
				user_newshell = optarg;
#else
				user_shell = optarg;
#endif
				sflg++;
				break;
			case 'u':
				user_newid = get_id (optarg);
				uflg++;
				break;
			case 'U':
				if (Lflg && pflg)
					usage ();

				Uflg++;
				break;
			default:
				usage ();
			}
			anyflag++;
		}
	}

	if (anyflag == 0) {
		fprintf (stderr, _("%s: no flags given\n"), Prog);
		exit (E_USAGE);
	}
	if (!is_shadow_pwd && (eflg || fflg)) {
		fprintf (stderr,
			 _
			 ("%s: shadow passwords required for -e and -f\n"),
			 Prog);
		exit (E_USAGE);
	}

	if (optind != argc - 1)
		usage ();

	if (aflg && (!Gflg)) {
		fprintf (stderr,
			 _("%s: -a flag is ONLY allowed with the -G flag\n"),
			 Prog);
		usage ();
		exit (E_USAGE);
	}

	if (dflg && strcmp (user_home, user_newhome) == 0)
		dflg = mflg = 0;

	if (uflg && user_id == user_newid)
		uflg = oflg = 0;

	if (lflg && getpwnam (user_newname)) {
		fprintf (stderr, _("%s: user %s exists\n"), Prog, user_newname);
		exit (E_NAME_IN_USE);
	}

	if (uflg && !oflg && getpwuid (user_newid)) {
		fprintf (stderr, _("%s: uid %lu is not unique\n"),
			 Prog, (unsigned long) user_newid);
		exit (E_UID_IN_USE);
	}
}

/*
 * close_files - close all of the files that were opened
 *
 *	close_files() closes all of the files that were opened for this new
 *	user. This causes any modified entries to be written out.
 */
static void close_files (void)
{
	if (!pw_close ()) {
		fprintf (stderr, _("%s: cannot rewrite password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_close ()) {
		fprintf (stderr,
			 _("%s: cannot rewrite shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd)
		spw_unlock ();
	(void) pw_unlock ();

	/*
	 * Close the DBM and/or flat files
	 */
	endpwent ();
	endspent ();
	endgrent ();
#ifdef	SHADOWGRP
	endsgent ();
#endif
}

/*
 * open_files - lock and open the password files
 *
 *	open_files() opens the two password files.
 */
static void open_files (void)
{
	if (!pw_lock ()) {
		fprintf (stderr, _("%s: unable to lock password file\n"), Prog);
		exit (E_PW_UPDATE);
	}
	if (!pw_open (O_RDWR)) {
		fprintf (stderr, _("%s: unable to open password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_lock ()) {
		fprintf (stderr,
			 _("%s: cannot lock shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
	if (is_shadow_pwd && !spw_open (O_RDWR)) {
		fprintf (stderr,
			 _("%s: cannot open shadow password file\n"), Prog);
		fail_exit (E_PW_UPDATE);
	}
}

/*
 * usr_update - create the user entries
 *
 *	usr_update() creates the password file entries for this user and
 *	will update the group entries if required.
 */
static void usr_update (void)
{
	struct passwd pwent;
	const struct passwd *pwd;

	struct spwd spent;
	const struct spwd *spwd = NULL;

	/*
	 * Locate the entry in /etc/passwd, which MUST exist.
	 */
	pwd = pw_locate (user_name);
	if (!pwd) {
		fprintf (stderr, _("%s: %s not found in /etc/passwd\n"),
			 Prog, user_name);
		fail_exit (E_NOTFOUND);
	}
	pwent = *pwd;
	new_pwent (&pwent);


	/* 
	 * Locate the entry in /etc/shadow. It doesn't have to exist, and
	 * won't be created if it doesn't.
	 */
	if (is_shadow_pwd && (spwd = spw_locate (user_name))) {
		spent = *spwd;
		new_spent (&spent);
	}

	if (lflg || uflg || gflg || cflg || dflg || sflg || pflg
	    || Lflg || Uflg) {
		if (!pw_update (&pwent)) {
			fprintf (stderr,
				 _("%s: error changing password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
		if (lflg && !pw_remove (user_name)) {
			fprintf (stderr,
				 _("%s: error removing password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
	}
	if (spwd && (lflg || eflg || fflg || pflg || Lflg || Uflg)) {
		if (!spw_update (&spent)) {
			fprintf (stderr,
				 _
				 ("%s: error adding new shadow password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
		if (lflg && !spw_remove (user_name)) {
			fprintf (stderr,
				 _
				 ("%s: error removing shadow password entry\n"),
				 Prog);
			fail_exit (E_PW_UPDATE);
		}
	}
}

/*
 * move_home - move the user's home directory
 *
 *	move_home() moves the user's home directory to a new location. The
 *	files will be copied if the directory cannot simply be renamed.
 */
static void move_home (void)
{
	struct stat sb;

	if (mflg && stat (user_home, &sb) == 0) {
		/*
		 * Don't try to move it if it is not a directory
		 * (but /dev/null for example).  --marekm
		 */
		if (!S_ISDIR (sb.st_mode))
			return;

		if (access (user_newhome, F_OK) == 0) {
			fprintf (stderr, _("%s: directory %s exists\n"),
				 Prog, user_newhome);
			fail_exit (E_HOMEDIR);
		} else if (rename (user_home, user_newhome)) {
			if (errno == EXDEV) {
				if (mkdir (user_newhome, sb.st_mode & 0777)) {
					fprintf (stderr,
						 _
						 ("%s: can't create %s\n"),
						 Prog, user_newhome);
				}
				if (chown (user_newhome, sb.st_uid, sb.st_gid)) {
					fprintf (stderr,
						 _("%s: can't chown %s\n"),
						 Prog, user_newhome);
					rmdir (user_newhome);
					fail_exit (E_HOMEDIR);
				}
				if (copy_tree (user_home, user_newhome,
					       uflg ? user_newid : -1,
					       gflg ? user_newgid : -1) == 0) {
					if (remove_tree (user_home) != 0 ||
					    rmdir (user_home) != 0)
						fprintf (stderr,
							 _
							 ("%s: warning: failed to completely remove old home directory %s"),
							 Prog, user_home);
#ifdef WITH_AUDIT
					audit_logger (AUDIT_USER_CHAUTHTOK,
						      Prog,
						      "moving home directory",
						      user_newname, user_newid,
						      1);
#endif
					return;
				}

				(void) remove_tree (user_newhome);
				(void) rmdir (user_newhome);
			}
			fprintf (stderr,
				 _
				 ("%s: cannot rename directory %s to %s\n"),
				 Prog, user_home, user_newhome);
			fail_exit (E_HOMEDIR);
		}
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			      "moving home directory", user_newname, user_newid,
			      1);
#endif
	}
	if (uflg || gflg) {
#ifdef WITH_AUDIT
		audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
			      "changing home directory owner", user_newname,
			      user_newid, 1);
#endif
		chown (dflg ? user_newhome : user_home,
		       uflg ? user_newid : user_id,
		       gflg ? user_newgid : user_gid);
	}
}

/*
 * update_files - update the lastlog and faillog files
 */
static void update_files (void)
{
	struct lastlog ll;
	struct faillog fl;
	int fd;

	/*
	 * Relocate the "lastlog" entries for the user. The old entry is
	 * left alone in case the UID was shared. It doesn't hurt anything
	 * to just leave it be.
	 */
	if ((fd = open (LASTLOG_FILE, O_RDWR)) != -1) {
		lseek (fd, (off_t) user_id * sizeof ll, SEEK_SET);
		if (read (fd, (char *) &ll, sizeof ll) == sizeof ll) {
			lseek (fd, (off_t) user_newid * sizeof ll, SEEK_SET);
			write (fd, (char *) &ll, sizeof ll);
		}
		close (fd);
	}

	/*
	 * Relocate the "faillog" entries in the same manner.
	 */
	if ((fd = open (FAILLOG_FILE, O_RDWR)) != -1) {
		lseek (fd, (off_t) user_id * sizeof fl, SEEK_SET);
		if (read (fd, (char *) &fl, sizeof fl) == sizeof fl) {
			lseek (fd, (off_t) user_newid * sizeof fl, SEEK_SET);
			write (fd, (char *) &fl, sizeof fl);
		}
		close (fd);
	}
}

#ifndef NO_MOVE_MAILBOX
/*
 * This is the new and improved code to carefully chown/rename the user's
 * mailbox. Maybe I am too paranoid but the mail spool dir sometimes
 * happens to be mode 1777 (this makes mail user agents work without
 * being setgid mail, but is NOT recommended; they all should be fixed
 * to use movemail).  --marekm
 */
static void move_mailbox (void)
{
	const char *maildir;
	char mailfile[1024], newmailfile[1024];
	int fd;
	struct stat st;

	maildir = getdef_str ("MAIL_DIR");
#ifdef MAIL_SPOOL_DIR
	if (!maildir && !getdef_str ("MAIL_FILE"))
		maildir = MAIL_SPOOL_DIR;
#endif
	if (!maildir)
		return;

	/*
	 * O_NONBLOCK is to make sure open won't hang on mandatory locks.
	 * We do fstat/fchown to make sure there are no races (someone
	 * replacing /var/spool/mail/luser with a hard link to /etc/passwd
	 * between stat and chown).  --marekm
	 */
	snprintf (mailfile, sizeof mailfile, "%s/%s", maildir, user_name);
	fd = open (mailfile, O_RDONLY | O_NONBLOCK, 0);
	if (fd < 0) {
		/* no need for warnings if the mailbox doesn't exist */
		if (errno != ENOENT)
			perror (mailfile);
		return;
	}
	if (fstat (fd, &st) < 0) {
		perror ("fstat");
		close (fd);
		return;
	}
	if (st.st_uid != user_id) {
		/* better leave it alone */
		fprintf (stderr, _("%s: warning: %s not owned by %s\n"),
			 Prog, mailfile, user_name);
		close (fd);
		return;
	}
	if (uflg) {
		if (fchown (fd, user_newid, (gid_t) - 1) < 0) {
			perror (_("failed to change mailbox owner"));
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
				      "changing mail file owner", user_newname,
				      user_newid, 1);
		}
#endif
	}

	close (fd);

	if (lflg) {
		snprintf (newmailfile, sizeof newmailfile, "%s/%s",
			  maildir, user_newname);
		if (link (mailfile, newmailfile) || unlink (mailfile)) {
			perror (_("failed to rename mailbox"));
		}
#ifdef WITH_AUDIT
		else {
			audit_logger (AUDIT_USER_CHAUTHTOK, Prog,
				      "changing mail file name", user_newname,
				      user_newid, 1);
		}
#endif
	}
}
#endif

/*
 * main - usermod command
 */
int main (int argc, char **argv)
{
	int grp_err = 0;

#ifdef USE_PAM
	pam_handle_t *pamh = NULL;
	struct passwd *pampw;
	int retval;
#endif

#ifdef WITH_AUDIT
	audit_help_open ();
#endif

	/*
	 * Get my name so that I can use it to report errors.
	 */
	Prog = Basename (argv[0]);

	setlocale (LC_ALL, "");
	bindtextdomain (PACKAGE, LOCALEDIR);
	textdomain (PACKAGE);

	sys_ngroups = sysconf (_SC_NGROUPS_MAX);
	user_groups = malloc ((1 + sys_ngroups) * sizeof (char *));
	user_groups[0] = (char *) 0;

	OPENLOG ("usermod");

	is_shadow_pwd = spw_file_present ();
#ifdef SHADOWGRP
	is_shadow_grp = sgr_file_present ();
#endif

	process_flags (argc, argv);

#ifdef USE_PAM
	retval = PAM_SUCCESS;

	pampw = getpwuid (getuid ());
	if (pampw == NULL) {
		retval = PAM_USER_UNKNOWN;
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_start ("usermod", pampw->pw_name, &conv, &pamh);
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_authenticate (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval == PAM_SUCCESS) {
		retval = pam_acct_mgmt (pamh, 0);
		if (retval != PAM_SUCCESS) {
			pam_end (pamh, retval);
		}
	}

	if (retval != PAM_SUCCESS) {
		fprintf (stderr, _("%s: PAM authentication failed\n"), Prog);
		exit (1);
	}
#endif				/* USE_PAM */

	/*
	 * Do the hard stuff - open the files, change the user entries,
	 * change the home directory, then close and update the files.
	 */
	open_files ();

	usr_update ();
	nscd_flush_cache ("passwd");
	nscd_flush_cache ("group");

	close_files ();

	if (Gflg || lflg)
		grp_err = grp_update ();

	if (mflg)
		move_home ();

#ifndef NO_MOVE_MAILBOX
	if (lflg || uflg)
		move_mailbox ();
#endif

	if (uflg) {
		update_files ();

		/*
		 * Change the UID on all of the files owned by `user_id' to
		 * `user_newid' in the user's home directory.
		 */
		chown_tree (dflg ? user_newhome : user_home,
			    user_id, user_newid,
			    user_gid, gflg ? user_newgid : user_gid);
	}

	if (grp_err)
		exit (E_GRP_UPDATE);

#ifdef USE_PAM
	if (retval == PAM_SUCCESS)
		pam_end (pamh, PAM_SUCCESS);
#endif				/* USE_PAM */

	exit (E_SUCCESS);
	/* NOT REACHED */
}
Esempio n. 19
0
//
// Allocate and return the list of users on this system
//
int32_t scap_create_userlist(scap_t* handle)
{
	uint32_t usercnt;
	uint32_t grpcnt;
	struct passwd *p;
	struct group *g;

	//
	// If the list of users was already allocated for this handle (for example because this is
	// not the first user list block), free it
	//
	if(handle->m_userlist != NULL)
	{
		scap_free_userlist(handle->m_userlist);
		handle->m_userlist = NULL;
	}

	//
	// First pass: count the number of users and the number of groups
	//
	setpwent();
	p = getpwent();
	for(usercnt = 0; p; p = getpwent(), usercnt++); 
	endpwent();

	setgrent();
	g = getgrent();
	for(grpcnt = 0; g; g = getgrent(), grpcnt++);
	endgrent();

	//
	// Memory allocations
	//
	handle->m_userlist = (scap_userlist*)malloc(sizeof(scap_userlist));
	if(handle->m_userlist == NULL)
	{
		snprintf(handle->m_lasterr,	SCAP_LASTERR_SIZE, "userlist allocation failed(1)");
		return SCAP_FAILURE;
	}

	handle->m_userlist->nusers = usercnt;
	handle->m_userlist->ngroups = grpcnt;
	handle->m_userlist->totsavelen = 0;
	handle->m_userlist->users = (scap_userinfo*)malloc(usercnt * sizeof(scap_userinfo));
	if(handle->m_userlist->users == NULL)
	{
		snprintf(handle->m_lasterr,	SCAP_LASTERR_SIZE, "userlist allocation failed(2)");
		free(handle->m_userlist);
		return SCAP_FAILURE;		
	}

	handle->m_userlist->groups = (scap_groupinfo*)malloc(grpcnt * sizeof(scap_groupinfo));
	if(handle->m_userlist->groups == NULL)
	{
		snprintf(handle->m_lasterr,	SCAP_LASTERR_SIZE, "grouplist allocation failed(2)");
		free(handle->m_userlist->users);
		free(handle->m_userlist);
		return SCAP_FAILURE;		
	}

	//
	// Second pass: copy the data
	//

	//users
	setpwent();
	p = getpwent();

	for(usercnt = 0; p; p = getpwent(), usercnt++)
	{
		handle->m_userlist->users[usercnt].uid = p->pw_uid;
		handle->m_userlist->users[usercnt].gid = p->pw_gid;
		
		if(p->pw_name)
		{
			strncpy(handle->m_userlist->users[usercnt].name, p->pw_name, sizeof(handle->m_userlist->users[usercnt].name));
		}
		else
		{
			*handle->m_userlist->users[usercnt].name = '\0';
		}

		if(p->pw_dir)
		{
			strncpy(handle->m_userlist->users[usercnt].homedir, p->pw_dir, sizeof(handle->m_userlist->users[usercnt].homedir));
		}
		else
		{
			*handle->m_userlist->users[usercnt].homedir = '\0';	
		}

		if(p->pw_shell)
		{
			strncpy(handle->m_userlist->users[usercnt].shell, p->pw_shell, sizeof(handle->m_userlist->users[usercnt].shell));
		}
		else
		{
			*handle->m_userlist->users[usercnt].shell = '\0';	
		}

		handle->m_userlist->totsavelen += 
			sizeof(uint8_t) + // type
			sizeof(uint32_t) + // uid
			sizeof(uint32_t) +  // gid
			strlen(handle->m_userlist->users[usercnt].name) + 2 + 
			strlen(handle->m_userlist->users[usercnt].homedir) + 2 +
			strlen(handle->m_userlist->users[usercnt].shell) + 2; 
	}

	endpwent();

	// groups
	setgrent();
	g = getgrent();

	for(grpcnt = 0; g; g = getgrent(), grpcnt++)
	{
		handle->m_userlist->groups[grpcnt].gid = g->gr_gid;

		if(g->gr_name)
		{
			strncpy(handle->m_userlist->groups[grpcnt].name, g->gr_name, sizeof(handle->m_userlist->groups[grpcnt].name));
		}
		else
		{
			*handle->m_userlist->groups[grpcnt].name = '\0';
		}

		handle->m_userlist->totsavelen += 
			sizeof(uint8_t) + // type
			sizeof(uint32_t) +  // gid
			strlen(handle->m_userlist->groups[grpcnt].name) + 2;
	}

	endgrent();

	return SCAP_SUCCESS;
}
Esempio n. 20
0
static int update_group (void)
{
	int is_member;
	int was_member;
	int changed;
	const struct group *grp;
	struct group *ngrp;

	/*
	 * Lock and open the group file. This will load all of the group
	 * entries.
	 */
	if (!gr_lock ()) {
		fprintf (stderr, _("%s: error locking group file\n"),
			 Prog);
		SYSLOG ((LOG_ERR, "error locking group file"));
		return -1;
	}
	if (!gr_open (O_RDWR)) {
		fprintf (stderr, _("%s: error opening group file\n"),
			 Prog);
		SYSLOG ((LOG_ERR, "error opening group file"));
		gr_unlock ();
		return -1;
	}

	changed = 0;

	/*
	 * Scan through the entire group file looking for the groups that
	 * the user is a member of.
	 */
	while ((grp = gr_next ())) {

		/*
		 * See if the user specified this group as one of their
		 * concurrent groups.
		 */
		was_member = is_on_list (grp->gr_mem, user_name);
		is_member = Gflg && is_on_list (user_groups, grp->gr_name);

		if (!was_member && !is_member)
			continue;

		ngrp = __gr_dup (grp);
		if (!ngrp) {
			fprintf (stderr,
				 _("%s: out of memory in update_group\n"),
				 Prog);
			gr_unlock ();
			return -1;
		}

		if (was_member && (!Gflg || is_member)) {
			if (lflg) {
				ngrp->gr_mem = del_list (ngrp->gr_mem,
							 user_name);
				ngrp->gr_mem = add_list (ngrp->gr_mem,
							 user_newname);
				changed = 1;
				SYSLOG ((LOG_INFO,
					 "change `%s' to `%s' in group `%s'",
					 user_name, user_newname,
					 ngrp->gr_name));
			}
		} else if (was_member && Gflg && !is_member) {
			ngrp->gr_mem = del_list (ngrp->gr_mem, user_name);
			changed = 1;
			SYSLOG ((LOG_INFO, "delete `%s' from group `%s'",
				 user_name, ngrp->gr_name));
		} else if (!was_member && Gflg && is_member) {
			ngrp->gr_mem = add_list (ngrp->gr_mem,
						 lflg ? user_newname :
						 user_name);
			changed = 1;
			SYSLOG ((LOG_INFO, "add `%s' to group `%s'",
				 lflg ? user_newname : user_name,
				 ngrp->gr_name));
		}
		if (!changed)
			continue;

		changed = 0;
		if (!gr_update (ngrp)) {
			fprintf (stderr,
				 _("%s: error adding new group entry\n"),
				 Prog);
			SYSLOG ((LOG_ERR, "error adding group entry"));
			gr_unlock ();
			return -1;
		}
#ifdef	NDBM
		/*
		 * Update the DBM group file with the new entry as well.
		 */
		if (!gr_dbm_update (ngrp)) {
			fprintf (stderr,
				 _("%s: cannot add new dbm group entry\n"),
				 Prog);
			SYSLOG ((LOG_ERR, "error adding dbm group entry"));
			gr_unlock ();
			return -1;
		}
#endif				/* NDBM */
	}
#ifdef NDBM
	endgrent ();
#endif				/* NDBM */
	if (!gr_close ()) {
		fprintf (stderr, _("%s: cannot rewrite group file\n"),
			 Prog);
		gr_unlock ();
		return -1;
	}
	gr_unlock ();
	return 0;
}
Esempio n. 21
0
static int
findgroupbyname(const char *name, struct group *grp, char *buf, size_t buflen, struct group **result)
{
    int rc;
# if defined(WITH_PAM_USER_LOOKUP) || \
     ( defined(WITH_FILE_USER_LOOKUP) && \
       !( defined(HAVE_FGETGRENT_R) && defined(HAVE_FGETPWENT_R) ) )
    rc = pthread_mutex_lock( &pw_gr_serializer );
    if( rc != 0 )
        return ENOENT;
# endif

# if defined(WITH_PAM_USER_LOOKUP)
    setgrent();
#  if defined(HAVE_GETGRGID_R)
    rc = getgrnam_r( name, grp, buf, buflen, result );
#  elif defined(HAVE_GETGRGID)
#   error non-reentrant function support using getgrgid() currently not implemented
#  else
#   error neither getgrgid_r() nor getgrgid() available
#  endif
    endgrent();
# elif defined(WITH_FILE_USER_LOOKUP)
    if( name == 0 )
    {
        if( result )
            *result = 0;

        rc = ENOENT;
    }
    else
    {
        FILE *fp = fopen( "/etc/group", "r" );
        if( 0 == fp )
        {
            rc = errno;
        }
        else
        {
#  if defined(HAVE_FGETGRENT_R)
            while( 0 == ( rc = fgetgrent_r( fp, grp, buf, buflen, result ) ) )
            {
                if( (grp->gr_name != 0) && strcmp( name, grp->gr_name ) == 0 )
                    break;
            }

            if( ( rc != 0 ) && ( result != 0 ) )
                *result = 0;

#  elif defined(HAVE_FGETGRENT)
#   error non-reentrant function support using fgetgrent() currently not implemented
#  else
#   error neither fgetgrent_r() nor fgetgrent() available
#  endif
            fclose( fp );
        }
    }
# endif

# if defined(WITH_PAM_USER_LOOKUP) || \
     ( defined(WITH_FILE_USER_LOOKUP) && \
       !( defined(HAVE_FGETGRENT_R) && defined(HAVE_FGETPWENT_R) ) )
    pthread_mutex_unlock( &pw_gr_serializer );
# endif

    return rc;
}
Esempio n. 22
0
int MOSGetGListFromUName(

  char *UName,    /* I */
  char *Buf,      /* O (optional) */
  int  *GList,    /* O (optional) - terminated w/-1 */
  int   BufSize,  /* I */
  int  *GCount)   /* I (optional) */

  {
  char *BPtr = NULL;
  int   BSpace = 0;

  struct group *GPtr;
  int           uindex;
  int           gindex;

  char GName[MMAX_NAME];

  if ((UName == NULL) || (MSched.OSCredLookup == mapNever))
    {
    return(FAILURE);
    }

  /* FORMAT:  <GNAME>[,<GNAME>]... */

  if (Buf != NULL)
    MUSNInit(&BPtr,&BSpace,Buf,BufSize);

  gindex = MUGIDFromUser(-1,UName,GName);

  if (GList != NULL)
    GList[0] = gindex;

  if (Buf != NULL)
    {
    MUSNPrintF(&BPtr,&BSpace,"%s",
      GName);
    }

  setgrent();

  /* walk all groups, walk all users in each group (less efficient) */

  gindex = 1;

  while ((GPtr = getgrent()) != NULL)
    {
    for (uindex = 0;GPtr->gr_mem[uindex] != NULL;uindex++)
      {
      if (!strcmp(GPtr->gr_mem[uindex],UName))
        {
        if (Buf != NULL)
          {
          if (BPtr > Buf)
            MUSNCat(&BPtr,&BSpace,",");

          MUSNPrintF(&BPtr,&BSpace,"%s",
            GPtr->gr_name);
          }
        else 
          {
          if (GList != NULL)
            GList[gindex] = GPtr->gr_gid;
     
          gindex++;

          if (gindex >= (BufSize - 1))
            break;
          }

        break;
        }
      }  /* END for (uindex) */
    }    /* END while (getgrent() != NULL) */

  endgrent();

  if (GList != NULL)
    GList[gindex] = -1;

  if (GCount != NULL)
    *GCount = gindex;

  return(SUCCESS);
  }  /* END MOSGetGListFromUName() */
Esempio n. 23
0
static char *validate_group(char *group, DATA_BLOB password,int snum)
{
#ifdef HAVE_NETGROUP
	{
		char *host, *user, *domain;
		setnetgrent(group);
		while (getnetgrent(&host, &user, &domain)) {
			if (user) {
				if (user_ok(user, snum) && 
				    password_ok(user,password)) {
					endnetgrent();
					return(user);
				}
			}
		}
		endnetgrent();
	}
#endif

#ifdef HAVE_GETGRENT
	{
		struct group *gptr;
		setgrent();
		while ((gptr = (struct group *)getgrent())) {
			if (strequal(gptr->gr_name,group))
				break;
		}

		/*
		 * As user_ok can recurse doing a getgrent(), we must
		 * copy the member list onto the heap before
		 * use. Bug pointed out by [email protected].
		 */

		if (gptr) {
			char *member_list = NULL;
			size_t list_len = 0;
			char *member;
			int i;

			for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
				list_len += strlen(gptr->gr_mem[i])+1;
			}
			list_len++;

			member_list = (char *)SMB_MALLOC(list_len);
			if (!member_list) {
				endgrent();
				return NULL;
			}

			*member_list = '\0';
			member = member_list;

			for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
				size_t member_len = strlen(gptr->gr_mem[i])+1;

				DEBUG(10,("validate_group: = gr_mem = "
					  "%s\n", gptr->gr_mem[i]));

				safe_strcpy(member, gptr->gr_mem[i],
					list_len - (member-member_list));
				member += member_len;
			}

			endgrent();

			member = member_list;
			while (*member) {
				if (user_ok(member,snum) &&
				    password_ok(member,password)) {
					char *name = talloc_strdup(talloc_tos(),
								member);
					SAFE_FREE(member_list);
					return name;
				}

				DEBUG(10,("validate_group = member = %s\n",
					  member));

				member += strlen(member) + 1;
			}

			SAFE_FREE(member_list);
		} else {
			endgrent();
			return NULL;
		}
	}
#endif
	return(NULL);
}
Esempio n. 24
0
int
main(int argc, char **argv)
{
	struct fstab *fs;
	struct passwd *pw;
	struct group *gr;
	int gflag = 0, uflag = 0, errs = 0;
	long i, argnum, done = 0;
	char ch, *qfnp;

	while ((ch = getopt(argc, argv, "aguv")) != -1) {
		switch(ch) {
		case 'a':
			aflag++;
			break;
		case 'g':
			gflag++;
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			vflag++;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (argc == 0 && !aflag)
		usage();
	if (!gflag && !uflag) {
		if (aflag)
			gflag++;
		uflag++;
	}
	if (gflag) {
		setgrent();
		while ((gr = getgrent()) != 0)
			addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name);
		endgrent();
	}
	if (uflag) {
		setpwent();
		while ((pw = getpwent()) != 0)
			addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name);
		endpwent();
	}
	setfsent();
	while ((fs = getfsent()) != NULL) {
		if (strcmp(fs->fs_vfstype, "ufs"))
			continue;
		if (aflag) {
			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
				errs += repquota(fs, GRPQUOTA, qfnp);
			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
				errs += repquota(fs, USRQUOTA, qfnp);
			continue;
		}
		if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		    (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) {
			done |= 1 << argnum;
			if (gflag && hasquota(fs, GRPQUOTA, &qfnp))
				errs += repquota(fs, GRPQUOTA, qfnp);
			if (uflag && hasquota(fs, USRQUOTA, &qfnp))
				errs += repquota(fs, USRQUOTA, qfnp);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			warnx("%s not found in fstab", argv[i]);
	exit(errs);
}
Esempio n. 25
0
int main(int argc, const char *argv[]) {
    struct passwd *pw;
    struct group   *gp;
    int      current_user = 0;
    uid_t   id;
    int i;

    if (argc > 2) 
        usage(1, NULL);

    if (argc == 1) {
        id = getuid();
        current_user = 1;
        if (!(pw = getpwuid(id)))
            usage(1, "Username does not exist");
    } else {
        if (!(pw = getpwnam(argv[1])))
            usage(1, "Username does not exist");
        id = pw->pw_uid;
    }

    printf("uid=%d(%s)", id, pw->pw_name);
    if ((gp = getgrgid(pw->pw_gid)))
        printf(" gid=%d(%s)", pw->pw_gid, gp->gr_name);

    if (current_user) {
        gid_t *gid_list;
        int      gid_size;

        if (getuid() != geteuid()) {
            id = geteuid();
            if (!(pw = getpwuid(id)))
                usage(1, "Username does not exist");
            printf(" euid=%d(%s)", id, pw->pw_name);
        }

        if (getgid() != getegid()) {
            id = getegid();
            if (!(gp = getgrgid(id)))
                usage(1, "Group does not exist");
            printf(" egid=%d(%s)", id, gp->gr_name);
        }

        /* use getgroups interface to get current groups */
        gid_size = getgroups(0, NULL);
        if (gid_size) {
            gid_list = malloc(gid_size * sizeof(gid_t));
            getgroups(gid_size, gid_list);

            for (i = 0; i < gid_size; i++) {
                if (!(gp = getgrgid(gid_list[i])))
                    die("Group does not exist");
                printf("%s%d(%s)", (i == 0) ? " groups=" : ",",
                                   gp->gr_gid, gp->gr_name);
            }

            free(gid_list);
        }
    } else {
        /* get list of groups from group database */
        i = 0;
        while ((gp = getgrent())) {
            char *c = *(gp->gr_mem);

            while (c && *c) {
                if (!strncmp(c, pw->pw_name, 16)) {
                    printf("%s%d(%s)", 
			   (i++ == 0) ? " groups=" : ",",
			   gp->gr_gid, gp->gr_name);
                    c = NULL;
                } else {
                    c++;
                }
            }
        }
        endgrent();
    }

    printf("\n");
    exit(0);
}
Esempio n. 26
0
KDModule::KDModule(QWidget *parent, const char *name, const QStringList &)
  : KCModule(KDMFactory::instance(), parent, name)
  , minshowuid(0)
  , maxshowuid(0)
  , updateOK(false)
{
  KAboutData *about =
    new KAboutData(I18N_NOOP("kcmkdm"), I18N_NOOP("KDE Login Manager Config Module"),
                0, 0, KAboutData::License_GPL,
                I18N_NOOP("(c) 1996 - 2005 The KDM Authors"));

  about->addAuthor("Thomas Tanghus", I18N_NOOP("Original author"), "*****@*****.**");
	about->addAuthor("Steffen Hansen", 0, "*****@*****.**");
	about->addAuthor("Oswald Buddenhagen", I18N_NOOP("Current maintainer"), "*****@*****.**");

  setQuickHelp( i18n(    "<h1>Login Manager</h1> In this module you can configure the "
                    "various aspects of the KDE Login Manager. This includes "
                    "the look and feel as well as the users that can be "
                    "selected for login. Note that you can only make changes "
                    "if you run the module with superuser rights. If you have not started the KDE "
                    "Control Center with superuser rights (which is absolutely the right thing to "
                    "do, by the way), click on the <em>Modify</em> button to acquire "
                    "superuser rights. You will be asked for the superuser password."
                    "<h2>Appearance</h2> On this tab page, you can configure how "
                    "the Login Manager should look, which language it should use, and which "
                    "GUI style it should use. The language settings made here have no influence on "
                    "the user's language settings."
                    "<h2>Font</h2>Here you can choose the fonts that the Login Manager should use "
                    "for various purposes like greetings and user names. "
                    "<h2>Background</h2>If you want to set a special background for the login "
                    "screen, this is where to do it."
                    "<h2>Shutdown</h2> Here you can specify who is allowed to shutdown/reboot the machine "
                    "and whether a boot manager should be used."
                    "<h2>Users</h2>On this tab page, you can select which users the Login Manager "
                    "will offer you for logging in."
                    "<h2>Convenience</h2> Here you can specify a user to be logged in automatically, "
		    "users not needing to provide a password to log in, and other convenience features.<br>"
		    "Note, that these settings are security holes by their nature, so use them very carefully."));

  setAboutData( about );

  setlocale( LC_COLLATE, "C" );

  KGlobal::locale()->insertCatalogue("kcmbackground");

  QStringList sl;
  QMap<gid_t,QStringList> tgmap;
  QMap<gid_t,QStringList>::Iterator tgmapi;
  QMap<gid_t,QStringList>::ConstIterator tgmapci;
  QMap<QString, QPair<int,QStringList> >::Iterator umapi;

  struct passwd *ps;
  for (setpwent(); (ps = getpwent()); ) {
    QString un( QFile::decodeName( ps->pw_name ) );
    if (usermap.find( un ) == usermap.end()) {
      usermap.insert( un, QPair<int,QStringList>( ps->pw_uid, sl ) );
      if ((tgmapi = tgmap.find( ps->pw_gid )) != tgmap.end())
        (*tgmapi).append( un );
      else
	tgmap[ps->pw_gid] = un;
    }
  }
  endpwent();

  struct group *grp;
  for (setgrent(); (grp = getgrent()); ) {
    QString gn( QFile::decodeName( grp->gr_name ) );
    bool delme = false;
    if ((tgmapi = tgmap.find( grp->gr_gid )) != tgmap.end()) {
      if ((*tgmapi).count() == 1 && (*tgmapi).first() == gn)
        delme = true;
      else
        for (QStringList::ConstIterator it = (*tgmapi).begin();
             it != (*tgmapi).end(); ++it)
          usermap[*it].second.append( gn );
      tgmap.remove( tgmapi );
    }
    if (!*grp->gr_mem ||
        (delme && !grp->gr_mem[1] && gn == QFile::decodeName( *grp->gr_mem )))
      continue;
    do {
      QString un( QFile::decodeName( *grp->gr_mem ) );
      if ((umapi = usermap.find( un )) != usermap.end()) {
        if ((*umapi).second.find( gn ) == (*umapi).second.end())
	  (*umapi).second.append( gn );
      } else
        kdWarning() << "group '" << gn << "' contains unknown user '" << un << "'" << endl;
    } while (*++grp->gr_mem);
  }
  endgrent();

  for (tgmapci = tgmap.begin(); tgmapci != tgmap.end(); ++tgmapci)
    kdWarning() << "user(s) '" << tgmapci.data().join(",")
	<< "' have unknown GID " << tgmapci.key() << endl;

  config = new KSimpleConfig( QString::fromLatin1( KDE_CONFDIR "/kdm/kdmrc" ));

  QVBoxLayout *top = new QVBoxLayout(this);
  tab = new QTabWidget(this);

  // *****
  // _don't_ add a theme configurator until the theming engine is _really_ done!!
  // *****

  appearance = new KDMAppearanceWidget(this);
  tab->addTab(appearance, i18n("A&ppearance"));
  connect(appearance, SIGNAL(changed(bool)), SIGNAL( changed(bool)));

  font = new KDMFontWidget(this);
  tab->addTab(font, i18n("&Font"));
  connect(font, SIGNAL(changed(bool)), SIGNAL(changed(bool)));

  background = new KBackground(this);
  tab->addTab(background, i18n("&Background"));
  connect(background, SIGNAL(changed(bool)), SIGNAL(changed(bool)));

  sessions = new KDMSessionsWidget(this);
  tab->addTab(sessions, i18n("&Shutdown"));
  connect(sessions, SIGNAL(changed(bool)), SIGNAL(changed(bool)));

  users = new KDMUsersWidget(this, 0);
  tab->addTab(users, i18n("&Users"));
  connect(users, SIGNAL(changed(bool)), SIGNAL(changed(bool)));
  connect(users, SIGNAL(setMinMaxUID(int,int)), SLOT(slotMinMaxUID(int,int)));
  connect(this, SIGNAL(addUsers(const QMap<QString,int> &)), users, SLOT(slotAddUsers(const QMap<QString,int> &)));
  connect(this, SIGNAL(delUsers(const QMap<QString,int> &)), users, SLOT(slotDelUsers(const QMap<QString,int> &)));
  connect(this, SIGNAL(clearUsers()), users, SLOT(slotClearUsers()));

  convenience = new KDMConvenienceWidget(this, 0);
  tab->addTab(convenience, i18n("Con&venience"));
  connect(convenience, SIGNAL(changed(bool)), SIGNAL(changed(bool)));
  connect(this, SIGNAL(addUsers(const QMap<QString,int> &)), convenience, SLOT(slotAddUsers(const QMap<QString,int> &)));
  connect(this, SIGNAL(delUsers(const QMap<QString,int> &)), convenience, SLOT(slotDelUsers(const QMap<QString,int> &)));
  connect(this, SIGNAL(clearUsers()), convenience, SLOT(slotClearUsers()));

  load();
  if (getuid() != 0 || !config->checkConfigFilesWritable( true )) {
    appearance->makeReadOnly();
    font->makeReadOnly();
    background->makeReadOnly();
    users->makeReadOnly();
    sessions->makeReadOnly();
    convenience->makeReadOnly();
  }
  top->addWidget(tab);
}
Esempio n. 27
0
File: achown.c Progetto: jskDr/mc
static void
do_enter_key (WDialog * h, int f_pos)
{
    WListbox *chl_list;
    struct passwd *chl_pass;
    struct group *chl_grp;
    int fe;
    gboolean chl_end, is_owner;

    do
    {
        int result;
        WDialog *chl_dlg;
        const char *title;
        int lxx, lyy, b_pos;

        is_owner = (f_pos == 3);
        title = is_owner ? _("owner") : _("group");

        lxx = (COLS - 74) / 2 + (is_owner ? 35 : 53);
        lyy = (LINES - 13) / 2;
        chl_end = FALSE;

        chl_dlg =
            dlg_create (TRUE, lyy, lxx, 13, 17, WPOS_KEEP_DEFAULT, TRUE, dialog_colors,
                        chl_callback, NULL, "[Advanced Chown]", title);

        /* get new listboxes */
        chl_list = listbox_new (1, 1, 11, 15, FALSE, NULL);
        listbox_add_item (chl_list, LISTBOX_APPEND_AT_END, 0, "<Unknown>", NULL, FALSE);
        if (is_owner)
        {
            /* get and put user names in the listbox */
            setpwent ();
            while ((chl_pass = getpwent ()) != NULL)
                listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_pass->pw_name, NULL,
                                  FALSE);
            endpwent ();
            fe = listbox_search_text (chl_list, get_owner (sf_stat->st_uid));
        }
        else
        {
            /* get and put group names in the listbox */
            setgrent ();
            while ((chl_grp = getgrent ()) != NULL)
                listbox_add_item (chl_list, LISTBOX_APPEND_SORTED, 0, chl_grp->gr_name, NULL,
                                  FALSE);
            endgrent ();
            fe = listbox_search_text (chl_list, get_group (sf_stat->st_gid));
        }

        listbox_select_entry (chl_list, fe);

        b_pos = chl_list->pos;
        add_widget (chl_dlg, chl_list);

        result = dlg_run (chl_dlg);

        if (result != B_CANCEL)
        {
            if (b_pos != chl_list->pos)
            {
                gboolean ok = FALSE;
                char *text;

                listbox_get_current (chl_list, &text, NULL);
                if (is_owner)
                {
                    chl_pass = getpwnam (text);
                    if (chl_pass != NULL)
                    {
                        ok = TRUE;
                        sf_stat->st_uid = chl_pass->pw_uid;
                    }
                }
                else
                {
                    chl_grp = getgrnam (text);
                    if (chl_grp != NULL)
                    {
                        sf_stat->st_gid = chl_grp->gr_gid;
                        ok = TRUE;
                    }
                }
                if (ok)
                {
                    ch_flags[f_pos + 6] = '+';
                    update_ownership ();
                }
                dlg_focus (h);
                if (ok)
                    print_flags ();
            }
            if (result == KEY_LEFT)
            {
                if (!is_owner)
                    chl_end = TRUE;
                dlg_one_up (ch_dlg);
                f_pos--;
            }
            else if (result == KEY_RIGHT)
            {
                if (is_owner)
                    chl_end = TRUE;
                dlg_one_down (ch_dlg);
                f_pos++;
            }
        }

        /* Here we used to redraw the window */
        dlg_destroy (chl_dlg);
    }
    while (chl_end);
}
Esempio n. 28
0
struct sys_grent * getgrent_list(void)
{
	struct sys_grent *glist;
	struct sys_grent *gent;
	struct group *grp;
	
	gent = (struct sys_grent *) malloc(sizeof(struct sys_grent));
	if (gent == NULL) {
		DEBUG (0, ("Out of memory in getgrent_list!\n"));
		return NULL;
	}
	memset(gent, '\0', sizeof(struct sys_grent));
	glist = gent;
	
	setgrent();
	grp = getgrent();
	if (grp == NULL) {
		endgrent();
		SAFE_FREE(glist);
		return NULL;
	}

	while (grp != NULL) {
		int i,num;
		
		if (grp->gr_name) {
			if ((gent->gr_name = strdup(grp->gr_name)) == NULL)
				goto err;
		}
		if (grp->gr_passwd) {
			if ((gent->gr_passwd = strdup(grp->gr_passwd)) == NULL)
				goto err;
		}
		gent->gr_gid = grp->gr_gid;
		
		/* number of strings in gr_mem */
		for (num = 0; grp->gr_mem[num];	num++)
			;
		
		/* alloc space for gr_mem string pointers */
		if ((gent->gr_mem = (char **) malloc((num+1) * sizeof(char *))) == NULL)
			goto err;

		memset(gent->gr_mem, '\0', (num+1) * sizeof(char *));

		for (i=0; i < num; i++) {
			if ((gent->gr_mem[i] = strdup(grp->gr_mem[i])) == NULL)
				goto err;
		}
		gent->gr_mem[num] = NULL;
		
		grp = getgrent();
		if (grp) {
			gent->next = (struct sys_grent *) malloc(sizeof(struct sys_grent));
			if (gent->next == NULL)
				goto err;
			gent = gent->next;
			memset(gent, '\0', sizeof(struct sys_grent));
		}
	}
	
	endgrent();
	return glist;

  err:

	endgrent();
	DEBUG(0, ("Out of memory in getgrent_list!\n"));
	grent_free(glist);
	return NULL;
}
Esempio n. 29
0
int
main(int argc, char *argv[])
{
	struct fstab *fs;
	struct passwd *pw;
	struct group *gr;
	struct quotafile *qfu, *qfg;
	int i, argnum, maxrun, errs, ch;
	long done = 0;
	char *name;

	errs = maxrun = 0;
	while ((ch = getopt(argc, argv, "ac:guvl:")) != -1) {
		switch(ch) {
		case 'a':
			aflag++;
			break;
		case 'c':
			if (cflag)
				usage();
			cflag = atoi(optarg);
			break;
		case 'g':
			gflag++;
			break;
		case 'u':
			uflag++;
			break;
		case 'v':
			vflag++;
			break;
		case 'l':
			maxrun = atoi(optarg);
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if ((argc == 0 && !aflag) || (argc > 0 && aflag))
		usage();
	if (cflag && cflag != 32 && cflag != 64)
		usage();
	if (!gflag && !uflag) {
		gflag++;
		uflag++;
	}
	if (gflag) {
		setgrent();
		while ((gr = getgrent()) != NULL)
			(void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name,
			    NULL);
		endgrent();
	}
	if (uflag) {
		setpwent();
		while ((pw = getpwent()) != NULL)
			(void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name,
			    NULL);
		endpwent();
	}
	/*
	 * The maxrun (-l) option is now deprecated.
	 */
	if (maxrun > 0)
		warnx("the -l option is now deprecated");
	if (aflag)
		exit(checkfstab(uflag, gflag));
	if (setfsent() == 0)
		errx(1, "%s: can't open", FSTAB);
	while ((fs = getfsent()) != NULL) {
		if (((argnum = oneof(fs->fs_file, argv, argc)) >= 0 ||
		     (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) &&
		    (name = blockcheck(fs->fs_spec))) {
			done |= 1 << argnum;
			qfu = NULL;
			if (uflag)
				qfu = quota_open(fs, USRQUOTA, O_CREAT|O_RDWR);
			qfg = NULL;
			if (gflag)
				qfg = quota_open(fs, GRPQUOTA, O_CREAT|O_RDWR);
			if (qfu == NULL && qfg == NULL)
				continue;
			errs += chkquota(name, qfu, qfg);
			if (qfu)
				quota_close(qfu);
			if (qfg)
				quota_close(qfg);
		}
	}
	endfsent();
	for (i = 0; i < argc; i++)
		if ((done & (1 << i)) == 0)
			fprintf(stderr, "%s not found in %s\n",
				argv[i], FSTAB);
	exit(errs);
}
Esempio n. 30
0
static int
#if defined(USE_PAM) || defined(_AIX)
isNoPassAllowed( const char *un )
{
	struct passwd *pw = 0;
# ifdef HAVE_GETSPNAM /* (sic!) - not USESHADOW */
	struct spwd *spw;
# endif
#else
isNoPassAllowed( const char *un, struct passwd *pw )
{
#endif
	struct group *gr;
	char **fp;
	int hg;

	if (!*un)
		return 0;

	if (cursource != PWSRC_MANUAL)
		return 1;

	for (hg = 0, fp = td->noPassUsers; *fp; fp++)
		if (**fp == '@')
			hg = 1;
		else if (!strcmp( un, *fp ))
			return 1;
		else if (!strcmp( "*", *fp )) {
#if defined(USE_PAM) || defined(_AIX)
			if (!(pw = getpwnam( un )))
				return 0;
			if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*')
				continue;
# ifdef HAVE_GETSPNAM /* (sic!) - not USESHADOW */
			if ((spw = getspnam( un )) &&
			    (spw->sp_pwdp[0] == '!' || spw->sp_pwdp[0] == '*'))
					continue;
# endif
#endif
			if (pw->pw_uid)
				return 1;
		}

#if defined(USE_PAM) || defined(_AIX)
	if (hg && (pw || (pw = getpwnam( un )))) {
#else
	if (hg) {
#endif
		for (setgrent(); (gr = getgrent()); )
			for (fp = td->noPassUsers; *fp; fp++)
				if (**fp == '@' && !strcmp( gr->gr_name, *fp + 1 )) {
					if (pw->pw_gid == gr->gr_gid) {
						endgrent();
						return 1;
					}
					for (; *gr->gr_mem; gr->gr_mem++)
						if (!strcmp( un, *gr->gr_mem )) {
							endgrent();
							return 1;
						}
				}
		endgrent();
	}

	return 0;
}

#if !defined(USE_PAM) && !defined(_AIX) && defined(HAVE_SETUSERCONTEXT)
# define LC_RET0 do { login_close(lc); return 0; } while(0)
#else
# define LC_RET0 return 0
#endif

int
verify( GConvFunc gconv, int rootok )
{
#ifdef USE_PAM
	const char *psrv;
	struct pam_data pdata;
	int pretc, pnopass;
	char psrvb[64];
#elif defined(_AIX)
	char *msg, *curret;
	int i, reenter;
#else
	struct stat st;
	const char *nolg;
	char *buf;
	int fd;
# ifdef HAVE_GETUSERSHELL
	char *s;
# endif
# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)
	int tim, expir, warntime, quietlog;
# endif
#endif

	debug( "verify ...\n" );

#ifdef USE_PAM

	pnopass = FALSE;
	if (!strcmp( curtype, "classic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		if (isNoPassAllowed( curuser )) {
			gconv( GCONV_PASS_ND, 0 );
			if (!*curpass) {
				pnopass = TRUE;
				sprintf( psrvb, "%.31s-np", PAMService );
				psrv = psrvb;
			} else
				psrv = PAMService;
		} else
			psrv = PAMService;
		pdata.usecur = TRUE;
	} else {
		sprintf( psrvb, "%.31s-%.31s", PAMService, curtype );
		psrv = psrvb;
		pdata.usecur = FALSE;
	}
	pdata.gconv = gconv;
	if (!doPAMAuth( psrv, &pdata ))
		return 0;

#elif defined(_AIX)

	if ((td->displayType & d_location) == dForeign) {
		char *tmpch;
		strncpy( hostname, td->name, sizeof(hostname) - 1 );
		hostname[sizeof(hostname)-1] = '\0';
		if ((tmpch = strchr( hostname, ':' )))
			*tmpch = '\0';
	} else
		hostname[0] = '\0';

	/* tty names should only be 15 characters long */
# if 0
	for (i = 0; i < 15 && td->name[i]; i++) {
		if (td->name[i] == ':' || td->name[i] == '.')
			tty[i] = '_';
		else
			tty[i] = td->name[i];
	}
	tty[i] = '\0';
# else
	memcpy( tty, "/dev/xdm/", 9 );
	for (i = 0; i < 6 && td->name[i]; i++) {
		if (td->name[i] == ':' || td->name[i] == '.')
			tty[9 + i] = '_';
		else
			tty[9 + i] = td->name[i];
	}
	tty[9 + i] = '\0';
# endif

	if (!strcmp( curtype, "classic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		if (isNoPassAllowed( curuser )) {
			gconv( GCONV_PASS_ND, 0 );
			if (!*curpass) {
				debug( "accepting despite empty password\n" );
				goto done;
			}
		} else
			if (!gconv( GCONV_PASS, 0 ))
				return 0;
		enduserdb();
		msg = NULL;
		if ((i = authenticate( curuser, curpass, &reenter, &msg ))) {
			debug( "authenticate() failed: %s\n", msg );
			if (msg)
				free( msg );
			loginfailed( curuser, hostname, tty );
			if (i == ENOENT || i == ESAD)
				V_RET_AUTH;
			else
				V_RET_FAIL( 0 );
		}
		if (reenter) {
			logError( "authenticate() requests more data: %s\n", msg );
			free( msg );
			V_RET_FAIL( 0 );
		}
	} else if (!strcmp( curtype, "generic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		for (curret = 0;;) {
			msg = NULL;
			if ((i = authenticate( curuser, curret, &reenter, &msg ))) {
				debug( "authenticate() failed: %s\n", msg );
				if (msg)
					free( msg );
				loginfailed( curuser, hostname, tty );
				if (i == ENOENT || i == ESAD)
					V_RET_AUTH;
				else
					V_RET_FAIL( 0 );
			}
			if (curret)
				free( curret );
			if (!reenter)
				break;
			if (!(curret = gconv( GCONV_HIDDEN, msg )))
				return 0;
			free( msg );
		}
	} else {
		logError( "Unsupported authentication type %\"s requested\n", curtype );
		V_RET_FAIL( 0 );
	}
	if (msg) {
		displayStr( V_MSG_INFO, msg );
		free( msg );
	}

  done:

#else

	if (strcmp( curtype, "classic" )) {
		logError( "Unsupported authentication type %\"s requested\n", curtype );
		V_RET_FAIL( 0 );
	}

	if (!gconv( GCONV_USER, 0 ))
		return 0;

	if (!(p = getpwnam( curuser ))) {
		debug( "getpwnam() failed.\n" );
		gconv( GCONV_PASS, 0 );
		V_RET_AUTH;
	}
	if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
		debug( "account is locked\n" );
		gconv( GCONV_PASS, 0 );
		V_RET_AUTH;
	}

# ifdef USESHADOW
	if ((sp = getspnam( curuser ))) {
		p->pw_passwd = sp->sp_pwdp;
		if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
			debug( "account is locked\n" );
			gconv( GCONV_PASS, 0 );
			V_RET_AUTH;
		}
	} else
		debug( "getspnam() failed: %m. Are you root?\n" );
# endif

	if (!*p->pw_passwd) {
		if (!td->allowNullPasswd) {
			debug( "denying user with empty password\n" );
			gconv( GCONV_PASS, 0 );
			V_RET_AUTH;
		}
		goto nplogin;
	}

	if (isNoPassAllowed( curuser, p )) {
	  nplogin:
		gconv( GCONV_PASS_ND, 0 );
		if (!*curpass) {
			debug( "accepting password-less login\n" );
			goto done;
		}
	} else
		if (!gconv( GCONV_PASS, 0 ))
			return 0;

# ifdef KERBEROS
	if (p->pw_uid) {
		int ret;
		char realm[REALM_SZ];

		if (krb_get_lrealm( realm, 1 )) {
			logError( "Cannot get KerberosIV realm.\n" );
			V_RET_FAIL( 0 );
		}

		sprintf( krbtkfile, "%s.%.*s", TKT_ROOT, MAXPATHLEN - strlen( TKT_ROOT ) - 2, td->name );
		krb_set_tkt_string( krbtkfile );
		unlink( krbtkfile );

		ret = krb_verify_user( curuser, "", realm, curpass, 1, "rcmd" );
		if (ret == KSUCCESS) {
			chown( krbtkfile, p->pw_uid, p->pw_gid );
			debug( "KerberosIV verify succeeded\n" );
			goto done;
		} else if (ret != KDC_PR_UNKNOWN && ret != SKDC_CANT) {
			logError( "KerberosIV verification failure %\"s for %s\n",
			          krb_get_err_text( ret ), curuser );
			krbtkfile[0] = '\0';
			V_RET_FAIL( 0 );
		}
		debug( "KerberosIV verify failed: %s\n", krb_get_err_text( ret ) );
	}
	krbtkfile[0] = '\0';
# endif	 /* KERBEROS */

# if defined(ultrix) || defined(__ultrix__)
	if (authenticate_user( p, curpass, NULL ) < 0)
# elif defined(HAVE_PW_ENCRYPT)
	if (strcmp( pw_encrypt( curpass, p->pw_passwd ), p->pw_passwd ))
# elif defined(HAVE_CRYPT)
	if (strcmp( crypt( curpass, p->pw_passwd ), p->pw_passwd ))
# else
	if (strcmp( curpass, p->pw_passwd ))
# endif
	{
		debug( "password verify failed\n" );
		V_RET_AUTH;
	}

  done:

#endif /* !defined(USE_PAM) && !defined(_AIX) */

	debug( "restrict %s ...\n", curuser );

#if defined(USE_PAM) || defined(_AIX)
	if (!(p = getpwnam( curuser ))) {
		logError( "getpwnam(%s) failed.\n", curuser );
		V_RET_FAIL( 0 );
	}
#endif
	if (!p->pw_uid) {
		if (!rootok && !td->allowRootLogin)
			V_RET_FAIL( "Root logins are not allowed" );
		return 1; /* don't deny root to log in */
	}

#ifdef USE_PAM

	debug( " pam_acct_mgmt() ...\n" );
	pretc = pam_acct_mgmt( pamh, 0 );
	reInitErrorLog();
	debug( " pam_acct_mgmt() returned: %s\n", pam_strerror( pamh, pretc ) );
	if (pretc == PAM_NEW_AUTHTOK_REQD) {
		pdata.usecur = FALSE;
		pdata.gconv = conv_interact;
		/* pam will have output a message already, so no prepareErrorGreet() */
		if (gconv != conv_interact || pnopass) {
			pam_end( pamh, PAM_SUCCESS );
			pamh = 0;
			gSendInt( V_CHTOK_AUTH );
			/* this cannot auth the wrong user, as only classic auths get here */
			while (!doPAMAuth( PAMService, &pdata ))
				if (pdata.abort)
					return 0;
			gSendInt( V_PRE_OK );
		} else
			gSendInt( V_CHTOK );
		for (;;) {
			debug( " pam_chauthtok() ...\n" );
			pretc = pam_chauthtok( pamh, PAM_CHANGE_EXPIRED_AUTHTOK );
			reInitErrorLog();
			debug( " pam_chauthtok() returned: %s\n", pam_strerror( pamh, pretc ) );
			if (pdata.abort) {
				pam_end( pamh, PAM_SUCCESS );
				pamh = 0;
				return 0;
			}
			if (pretc == PAM_SUCCESS)
				break;
			/* effectively there is only PAM_AUTHTOK_ERR */
			gSendInt( V_FAIL );
		}
		if (curpass)
			free( curpass );
		curpass = newpass;
		newpass = 0;
	} else if (pretc != PAM_SUCCESS) {
		pam_end( pamh, pretc );
		pamh = 0;
		V_RET_AUTH;
	}

#elif defined(_AIX) /* USE_PAM */

	msg = NULL;
	if (loginrestrictions( curuser,
	                       ((td->displayType & d_location) == dForeign) ? S_RLOGIN : S_LOGIN,
	                       tty, &msg ) == -1)
	{
		debug( "loginrestrictions() - %s\n", msg ? msg : "error" );
		loginfailed( curuser, hostname, tty );
		prepareErrorGreet();
		if (msg) {
			displayStr( V_MSG_ERR, msg );
			free( msg );
		}
		gSendInt( V_AUTH );
		return 0;
	}
	if (msg)
		free( (void *)msg );

#endif /* USE_PAM || _AIX */

#ifndef _AIX

# ifdef HAVE_SETUSERCONTEXT
#  ifdef HAVE_LOGIN_GETCLASS
	lc = login_getclass( p->pw_class );
#  else
	lc = login_getpwclass( p );
#  endif
	if (!lc)
		V_RET_FAIL( 0 );

	p->pw_shell = login_getcapstr( lc, "shell", p->pw_shell, p->pw_shell );
# endif

# ifndef USE_PAM

/* restrict_expired */
#  if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)

#   if !defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || (!defined(HAVE_SETUSERCONTEXT) && defined(USESHADOW))
	if (sp)
#   endif
	{

#   define DEFAULT_WARN	(2L * 7L)  /* Two weeks */

		tim = time( NULL ) / 86400L;

#   ifdef HAVE_SETUSERCONTEXT
		quietlog = login_getcapbool( lc, "hushlogin", 0 );
		warntime = login_getcaptime( lc, "warnexpire",
		                             DEFAULT_WARN * 86400L,
		                             DEFAULT_WARN * 86400L ) / 86400L;
#   else
		quietlog = 0;
#    ifdef USESHADOW
		warntime = sp->sp_warn != -1 ? sp->sp_warn : DEFAULT_WARN;
#    else
		warntime = DEFAULT_WARN;
#    endif
#   endif

#   ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
		if (p->pw_expire) {
			expir = p->pw_expire / 86400L;
#   else
		if (sp->sp_expire != -1) {
			expir = sp->sp_expire;
#   endif
			if (tim > expir) {
				displayStr( V_MSG_ERR,
				            "Your account has expired;"
				            " please contact your system administrator" );
				gSendInt( V_FAIL );
				LC_RET0;
			} else if (tim > (expir - warntime) && !quietlog) {
				displayMsg( V_MSG_INFO,
				            "Warning: your account will expire in %d day(s)",
				            expir - tim );
			}
		}

#   ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
		if (p->pw_change) {
			expir = p->pw_change / 86400L;
#   else
		if (!sp->sp_lstchg) {
			displayStr( V_MSG_ERR,
			            "You are required to change your password immediately"
			            " (root enforced)" );
			/* XXX todo password change */
			gSendInt( V_FAIL );
			LC_RET0;
		} else if (sp->sp_max != -1) {
			expir = sp->sp_lstchg + sp->sp_max;
			if (sp->sp_inact != -1 && tim > expir + sp->sp_inact) {
				displayStr( V_MSG_ERR,
				            "Your account has expired;"
				            " please contact your system administrator" );
				gSendInt( V_FAIL );
				LC_RET0;
			}
#   endif
			if (tim > expir) {
				displayStr( V_MSG_ERR,
				            "You are required to change your password immediately"
				            " (password aged)" );
				/* XXX todo password change */
				gSendInt( V_FAIL );
				LC_RET0;
			} else if (tim > (expir - warntime) && !quietlog) {
				displayMsg( V_MSG_INFO,
				            "Warning: your password will expire in %d day(s)",
				            expir - tim );
			}
		}

	}

#  endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE || USESHADOW */

/* restrict_nologin */
#  ifndef _PATH_NOLOGIN
#   define _PATH_NOLOGIN "/etc/nologin"
#  endif

	if ((
#  ifdef HAVE_SETUSERCONTEXT
	     /* Do we ignore a nologin file? */
	     !login_getcapbool( lc, "ignorenologin", 0 )) &&
	    (!stat( (nolg = login_getcapstr( lc, "nologin", "", NULL )), &st ) ||
#  endif
		 !stat( (nolg = _PATH_NOLOGIN), &st )))
	{
		if (st.st_size && (fd = open( nolg, O_RDONLY )) >= 0) {
			if ((buf = Malloc( st.st_size + 1 ))) {
				if (read( fd, buf, st.st_size ) == st.st_size) {
					close( fd );
					buf[st.st_size] = 0;
					displayStr( V_MSG_ERR, buf );
					free( buf );
					gSendInt( V_FAIL );
					LC_RET0;
				}
				free( buf );
			}
			close( fd );
		}
		displayStr( V_MSG_ERR,
		            "Logins are not allowed at the moment.\nTry again later" );
		gSendInt( V_FAIL );
		LC_RET0;
	}

/* restrict_time */
#  if defined(HAVE_SETUSERCONTEXT) && defined(HAVE_AUTH_TIMEOK)
	if (!auth_timeok( lc, time( NULL ) )) {
		displayStr( V_MSG_ERR,
		            "You are not allowed to login at the moment" );
		gSendInt( V_FAIL );
		LC_RET0;
	}
#  endif

#  ifdef HAVE_GETUSERSHELL
	for (;;) {
		if (!(s = getusershell())) {
			debug( "shell not in /etc/shells\n" );
			endusershell();
			V_RET_FAIL( "Your login shell is not listed in /etc/shells" );
		}
		if (!strcmp( s, p->pw_shell )) {
			endusershell();
			break;
		}
	}
#  endif

# endif /* !USE_PAM */

/* restrict_nohome */
# ifdef HAVE_SETUSERCONTEXT
	if (login_getcapbool( lc, "requirehome", 0 )) {
		struct stat st;
		if (!*p->pw_dir || stat( p->pw_dir, &st ) || st.st_uid != p->pw_uid) {
			displayStr( V_MSG_ERR, "Home folder not available" );
			gSendInt( V_FAIL );
			LC_RET0;
		}
	}
# endif

#endif /* !_AIX */

	return 1;

}


static const char *envvars[] = {
	"TZ", /* SYSV and SVR4, but never hurts */
#ifdef _AIX
	"AUTHSTATE", /* for kerberos */
#endif
	NULL
};


#if defined(USE_PAM) && defined(HAVE_INITGROUPS)
static int num_saved_gids;
static gid_t *saved_gids;

static int
saveGids( void )
{
	num_saved_gids = getgroups( 0, 0 );
	if (!(saved_gids = Malloc( sizeof(gid_t) * num_saved_gids )))
		return 0;
	if (getgroups( num_saved_gids, saved_gids ) < 0) {
		logError( "saving groups failed: %m\n" );
		return 0;
	}
	return 1;
}

static int
restoreGids( void )
{
	if (setgroups( num_saved_gids, saved_gids ) < 0) {
		logError( "restoring groups failed: %m\n" );
		return 0;
	}
	if (setgid( p->pw_gid ) < 0) {
		logError( "restoring gid failed: %m\n" );
		return 0;
	}
	return 1;
}
#endif /* USE_PAM && HAVE_INITGROUPS */

static int
resetGids( void )
{
#ifdef HAVE_INITGROUPS
	if (setgroups( 0, &p->pw_gid /* anything */ ) < 0) {
		logError( "restoring groups failed: %m\n" );
		return 0;
	}
#endif
	if (setgid( 0 ) < 0) {
		logError( "restoring gid failed: %m\n" );
		return 0;
	}
	return 1;
}

static int
setGid( const char *name, int gid )
{
	if (setgid( gid ) < 0) {
		logError( "setgid(%d) (user %s) failed: %m\n", gid, name );
		return 0;
	}
#ifdef HAVE_INITGROUPS
	if (initgroups( name, gid ) < 0) {
		logError( "initgroups for %s failed: %m\n", name );
		setgid( 0 );
		return 0;
	}
#endif	 /* QNX4 doesn't support multi-groups, no initgroups() */
	return 1;
}

static int
setUid( const char *name, int uid )
{
	if (setuid( uid ) < 0) {
		logError( "setuid(%d) (user %s) failed: %m\n", uid, name );
		return 0;
	}
	return 1;
}

static int
setUser( const char *name, int uid, int gid )
{
	if (setGid( name, gid )) {
		if (setUid( name, uid ))
			return 1;
		resetGids();
	}
	return 0;
}

#if defined(SECURE_RPC) || defined(K5AUTH)
static void
nukeAuth( int len, const char *name )
{
	int i;

	for (i = 0; i < td->authNum; i++)
		if (td->authorizations[i]->name_length == len &&
		    !memcmp( td->authorizations[i]->name, name, len ))
		{
			memcpy( &td->authorizations[i], &td->authorizations[i+1],
			        sizeof(td->authorizations[i]) * (--td->authNum - i) );
			break;
		}
}
#endif

static void
mergeSessionArgs( int cansave )
{
	char *mfname;
	const char *fname;
	int i, needsave;

	mfname = 0;
	fname = ".dmrc";
	if ((!curdmrc || newdmrc) && *dmrcDir)
		if (strApp( &mfname, dmrcDir, "/", curuser, fname, (char *)0 ))
			fname = mfname;
	needsave = 0;
	if (!curdmrc) {
		curdmrc = iniLoad( fname );
		if (!curdmrc) {
			strDup( &curdmrc, "[Desktop]\nSession=default\n" );
			needsave = 1;
		}
	}
	if (newdmrc) {
		curdmrc = iniMerge( curdmrc, newdmrc );
		needsave = 1;
	}
	if (needsave && cansave)
		if (!iniSave( curdmrc, fname ) && errno == ENOENT && mfname) {
			for (i = 0; mfname[i]; i++)
				if (mfname[i] == '/') {
					mfname[i] = 0;
					mkdir( mfname, 0755 );
					mfname[i] = '/';
				}
			iniSave( curdmrc, mfname );
		}
	if (mfname)
		free( mfname );
}

static int
createClientLog( const char *log )
{
	char randstr[32], *randstrp = 0, *lname;
	int lfd;

	for (;;) {
		struct expando macros[] = {
			{ 'd', 0, td->name },
			{ 'u', 0, curuser },
			{ 'r', 0, randstrp },
			{ 0, 0, 0 }
		};
		if (!(lname = expandMacros( log, macros )))
			exit( 1 );
		unlink( lname );
		if ((lfd = open( lname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) >= 0) {
			dup2( lfd, 1 );
			dup2( lfd, 2 );
			close( lfd );
			free( lname );
			return TRUE;
		}
		if (errno != EEXIST || !macros[2].uses) {
			free( lname );
			return FALSE;
		}
		logInfo( "Session log file %s not usable, trying another one.\n",
		         lname );
		free( lname );
		sprintf( randstr, "%d", secureRandom() );
		randstrp = randstr;
	}
}