int main(int argc, char *argv[]) { int c; char *interface; struct passwd *pw; extern char version[]; while ((c = getopt(argc, argv, "34adfv")) != -1) switch (c) { case '3': Not3Flag = 1; break; case '4': Not4Flag = 1; break; case 'a': AllFlag = 1; break; case 'd': DebugFlag++; break; case 'f': ForegroundFlag = 1; break; case 'v': VersionFlag = 1; break; default: Usage(); /* NOTREACHED */ } if (VersionFlag) { fprintf(stdout,"%s: version %s\n", __progname, version); exit(0); } interface = argv[optind++]; if ((AllFlag && interface) || (!AllFlag && interface == 0) || (argc > optind) || (Not3Flag && Not4Flag)) Usage(); /* All error reporting is done through syslogs. */ openlog(__progname, LOG_PID | LOG_CONS, LOG_DAEMON); tzset(); if ((pw = getpwnam("_mopd")) == NULL) err(1, "getpwnam"); if ((!ForegroundFlag) && DebugFlag) fprintf(stdout, "%s: not running as daemon, -d given.\n", __progname); if ((!ForegroundFlag) && (!DebugFlag)) if (daemon(0, 0) == -1) err(1, NULL); syslog(LOG_INFO, "%s %s started.", __progname, version); if (AllFlag) deviceInitAll(); else deviceInitOne(interface); if (chroot(MOP_FILE_PATH) == -1) { syslog(LOG_CRIT, "chroot %s: %m", MOP_FILE_PATH); exit(1); } if (chdir("/") == -1) { syslog(LOG_CRIT, "chdir(\"/\"): %m"); exit(1); } if (setgroups(1, &pw->pw_gid) || setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) { syslog(LOG_CRIT, "can't drop privileges: %m"); exit(1); } endpwent(); Loop(); /* NOTREACHED */ }
int yaz_daemon(const char *progname, unsigned int flags, void (*work)(void *data), void *data, const char *pidfile, const char *uid) { #if HAVE_PWD_H int pid_fd = -1; /* open pidfile .. defer write until in child and after setuid */ if (pidfile) { pid_fd = open(pidfile, O_CREAT|O_RDWR, 0666); if (pid_fd == -1) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "open %s", pidfile); exit(1); } } if (flags & YAZ_DAEMON_DEBUG) { /* in debug mode.. it's quite simple */ write_pidfile(pid_fd); work(data); exit(0); } /* running in production mode. */ if (uid) { /* OK to use the non-thread version here */ struct passwd *pw = getpwnam(uid); if (!pw) { yaz_log(YLOG_FATAL, "%s: Unknown user", uid); exit(1); } if (setuid(pw->pw_uid) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "setuid"); exit(1); } } if (flags & YAZ_DAEMON_FORK) { /* create pipe so that parent waits until child has created PID (or failed) */ static int hand[2]; /* hand shake for child */ if (pipe(hand) < 0) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "pipe"); return 1; } switch (fork()) { case 0: break; case -1: return 1; default: close(hand[1]); while(1) { char dummy[1]; int res = read(hand[0], dummy, 1); if (res < 0 && errno != EINTR) { yaz_log(YLOG_FATAL|YLOG_ERRNO, "read fork handshake"); break; } else if (res >= 0) break; } close(hand[0]); _exit(0); } /* child */ close(hand[0]); if (setsid() < 0) return 1; close(0); close(1); close(2); open("/dev/null", O_RDWR); if (dup(0) == -1) return 1; if (dup(0) == -1) return 1; close(hand[1]); } write_pidfile(pid_fd); if (flags & YAZ_DAEMON_KEEPALIVE) { keepalive(work, data); } else { work(data); } return 0; #else work(data); return 0; #endif }
static void godaemon (char *rundir, char *pidfile) { char str[10]; pid_t pid,sid,parent; int lfp = -1; // Check if parent process id is set if (getppid() == 1){ fprintf(stderr,"PPID exists, therefore we are already a daemon "); exit(EXIT_FAILURE); } /* Create the lock file as the current user */ if ( pidfile && pidfile[0] ) { lfp = open(pidfile,O_RDWR|O_CREAT,0640); if ( lfp < 0 ) { log_err("unable to create pid file %s, code=%d (%s)", pidfile, errno, strerror(errno) ); exit(EXIT_FAILURE); } /* Get and format PID */ sprintf(str,"%d\n",getpid()); int res = write(lfp, str, strlen(str)); if(res != strlen(str)){ log_err("Unable to write pid to file\n"); exit(EXIT_FAILURE); } } /* create the directory for temp data if need be */ mode_t process_mask = umask(0); char dirname[FILENAME_MAX_CHARS]; sprintf(dirname,"%s/%s",rundir,"bgpmon"); int result_code = mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO); if(result_code && errno != EEXIST){ log_err("Unable to create scratch dir %s\n",dirname); exit(EXIT_FAILURE); } result_code = umask(process_mask); if(result_code){ log_err("Unable to set mask\n"); exit(EXIT_FAILURE); } /* Drop user if there is one, and we were run as root */ if ( getuid() == 0 || geteuid() == 0 ) { struct passwd *pw = getpwnam(RUN_AS_USER); if ( pw ) { result_code = chown(dirname,pw->pw_uid,pw->pw_gid); if(result_code){ log_err("Unable to create scratch dir %s\n",dirname); exit(EXIT_FAILURE); } syslog( LOG_NOTICE, "setting user to " RUN_AS_USER ); setuid( pw->pw_uid ); } } /* Trap signals that we expect to recieve */ signal(SIGCHLD,child_handler); signal(SIGUSR1,child_handler); signal(SIGALRM,child_handler); /* Fork*/ pid = fork (); if (pid < 0) { log_err ("fork failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /* In case of this is parent process. */ if (pid > 0){ // Wait for confirmation from the child via SIGTERM or SIGCHLD, or // for two seconds to elapse (SIGALRM). pause() should not return. alarm(2); pause(); exit(EXIT_FAILURE); } // we are now the parent process parent = getppid(); /* Cancel certain signals */ signal(SIGCHLD,SIG_DFL); /* A child process dies */ signal(SIGTSTP,SIG_IGN); /* Various TTY signals */ signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGHUP, SIG_IGN); /* Ignore hangup signal */ signal(SIGTERM,SIG_DFL); /* Die on SIGTERM */ /* Change the file mode mask */ umask(0); /* Become session leader and get pid. */ sid = setsid(); if (sid < 0) { log_err ("setsid failed: %s", strerror(errno)); exit(EXIT_FAILURE); } /* Change the current working directory. This prevents the current directory from being locked; hence not being able to remove it. */ if ((chdir("/")) < 0) { syslog( LOG_ERR, "unable to change directory to %s, code %d (%s)", "/", errno, strerror(errno) ); exit(EXIT_FAILURE); } /* Redirect standard files to /dev/null */ FILE* res; res = freopen( "/dev/null", "r", stdin); if(res == NULL){ log_err("unable to redirect stdin\n"); exit(EXIT_FAILURE); } res = freopen( "/dev/null", "w", stdout); if(res == NULL){ log_err("unable to redirect stdout\n"); exit(EXIT_FAILURE); } res = freopen( "/dev/null", "w", stderr); if(res == NULL){ log_err("unable to redirect stderr\n"); exit(EXIT_FAILURE); } // let the parent know that all is good kill( parent, SIGUSR1 ); }
/* * Parse the argument to the -R or --owner flag. * * The format is one of the following: * <username|uid> - Override user but not group * <username>: - Override both, group is user's default group * <uid>: - Override user but not group * <username|uid>:<groupname|gid> - Override both * :<groupname|gid> - Override group but not user * * Where uid/gid are decimal representations and groupname/username * are names to be looked up in system database. Note that we try * to look up an argument as a name first, then try numeric parsing. * * A period can be used instead of the colon. * * Sets uid/gid return as appropriate, -1 indicates uid/gid not specified. * TODO: If the spec uses uname/gname, then return those to the caller * as well. If the spec provides uid/gid, just return names as NULL. * * Returns NULL if no error, otherwise returns error string for display. * */ const char * owner_parse(const char *spec, int *uid, int *gid) { static char errbuff[128]; const char *u, *ue, *g; *uid = -1; *gid = -1; if (spec[0] == '\0') return ("Invalid empty user/group spec"); /* * Split spec into [user][:.][group] * u -> first char of username, NULL if no username * ue -> first char after username (colon, period, or \0) * g -> first char of group name */ if (*spec == ':' || *spec == '.') { /* If spec starts with ':' or '.', then just group. */ ue = u = NULL; g = spec + 1; } else { /* Otherwise, [user] or [user][:] or [user][:][group] */ ue = u = spec; while (*ue != ':' && *ue != '.' && *ue != '\0') ++ue; g = ue; if (*g != '\0') /* Skip : or . to find first char of group. */ ++g; } if (u != NULL) { /* Look up user: ue is first char after end of user. */ char *user; struct passwd *pwent; user = (char *)malloc(ue - u + 1); if (user == NULL) return ("Couldn't allocate memory"); memcpy(user, u, ue - u); user[ue - u] = '\0'; if ((pwent = getpwnam(user)) != NULL) { *uid = pwent->pw_uid; if (*ue != '\0') *gid = pwent->pw_gid; } else { char *end; errno = 0; *uid = (int)strtoul(user, &end, 10); if (errno || *end != '\0') { snprintf(errbuff, sizeof(errbuff), "Couldn't lookup user ``%s''", user); errbuff[sizeof(errbuff) - 1] = '\0'; free(user); return (errbuff); } } free(user); } if (*g != '\0') { struct group *grp; if ((grp = getgrnam(g)) != NULL) { *gid = grp->gr_gid; } else { char *end; errno = 0; *gid = (int)strtoul(g, &end, 10); if (errno || *end != '\0') { snprintf(errbuff, sizeof(errbuff), "Couldn't lookup group ``%s''", g); errbuff[sizeof(errbuff) - 1] = '\0'; return (errbuff); } } } return (NULL); }
/** * thunar_util_expand_filename: * @filename : a local filename. * @working_directory : #GFile of the current working directory. * @error : return location for errors or %NULL. * * Takes a user-typed @filename and expands a tilde at the * beginning of the @filename. It also resolves paths prefixed with * '.' using the current working directory. * * The caller is responsible to free the returned string using * g_free() when no longer needed. * * Return value: the expanded @filename or %NULL on error. **/ gchar * thunar_util_expand_filename (const gchar *filename, GFile *working_directory, GError **error) { struct passwd *passwd; const gchar *replacement; const gchar *remainder; const gchar *slash; gchar *username; gchar *pwd; gchar *result = NULL; g_return_val_if_fail (filename != NULL, NULL); /* check if we have a valid (non-empty!) filename */ if (G_UNLIKELY (*filename == '\0')) { g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Invalid path")); return NULL; } /* check if we start with a '~' */ if (*filename == '~') { /* examine the remainder of the filename */ remainder = filename + 1; /* if we have only the slash, then we want the home dir */ if (G_UNLIKELY (*remainder == '\0')) return g_strdup (xfce_get_homedir ()); /* lookup the slash */ for (slash = remainder; *slash != '\0' && *slash != G_DIR_SEPARATOR; ++slash); /* check if a username was given after the '~' */ if (G_LIKELY (slash == remainder)) { /* replace the tilde with the home dir */ replacement = xfce_get_homedir (); } else { /* lookup the pwd entry for the username */ username = g_strndup (remainder, slash - remainder); passwd = getpwnam (username); g_free (username); /* check if we have a valid entry */ if (G_UNLIKELY (passwd == NULL)) { username = g_strndup (remainder, slash - remainder); g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, _("Unknown user \"%s\""), username); g_free (username); return NULL; } /* use the homedir of the specified user */ replacement = passwd->pw_dir; } /* generate the filename */ return g_build_filename (replacement, slash, NULL); } else if (*filename == '.') { /* examine the remainder of the filename */ remainder = filename + 1; /* transform working directory into a filename string */ if (G_LIKELY (working_directory != NULL)) { pwd = g_file_get_path (working_directory); /* if we only have the slash then we want the working directory only */ if (G_UNLIKELY (*remainder == '\0')) return pwd; /* concatenate working directory and remainder */ result = g_build_filename (pwd, remainder, G_DIR_SEPARATOR_S, NULL); /* free the working directory string */ g_free (pwd); } else result = g_strdup (filename); /* return the resulting path string */ return result; } return g_strdup (filename); }
static char * ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { #if (NGX_WIN32) ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"user\" is not supported, ignored"); return NGX_CONF_OK; #else ngx_core_conf_t *ccf = conf; char *group; struct passwd *pwd; struct group *grp; ngx_str_t *value; if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) { return "is duplicate"; } if (geteuid() != 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "the \"user\" directive makes sense only " "if the master process runs " "with super-user privileges, ignored"); return NGX_CONF_OK; } value = (ngx_str_t *) cf->args->elts; ccf->username = (char *) value[1].data; ngx_set_errno(0); pwd = getpwnam((const char *) value[1].data); if (pwd == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, "getpwnam(\"%s\") failed", value[1].data); return NGX_CONF_ERROR; } ccf->user = pwd->pw_uid; group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data); ngx_set_errno(0); grp = getgrnam(group); if (grp == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, "getgrnam(\"%s\") failed", group); return NGX_CONF_ERROR; } ccf->group = grp->gr_gid; return NGX_CONF_OK; #endif }
/* * main - userdel command */ int main (int argc, char **argv) { int errors = 0; /* Error in the removal of the home directory */ #ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM pam_handle_t *pamh = NULL; int retval; #endif /* USE_PAM */ #endif /* ACCT_TOOLS_SETUID */ #ifdef WITH_AUDIT audit_help_open (); #endif /* * Get my name so that I can use it to report errors. */ Prog = Basename (argv[0]); (void) setlocale (LC_ALL, ""); (void) bindtextdomain (PACKAGE, LOCALEDIR); (void) textdomain (PACKAGE); { /* * Parse the command line options. */ int c; static struct option long_options[] = { {"force", no_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {"remove", no_argument, NULL, 'r'}, {NULL, 0, NULL, '\0'} }; while ((c = getopt_long (argc, argv, "fhr", long_options, NULL)) != -1) { switch (c) { case 'f': /* force remove even if not owned by user */ fflg = true; break; case 'r': /* remove home dir and mailbox */ rflg = true; break; default: usage (); } } } if ((optind + 1) != argc) { usage (); } OPENLOG ("userdel"); #ifdef ACCT_TOOLS_SETUID #ifdef USE_PAM { struct passwd *pampw; pampw = getpwuid (getuid ()); /* local, no need for xgetpwuid */ if (pampw == NULL) { fprintf (stderr, _("%s: Cannot determine your user name.\n"), Prog); exit (E_PW_UPDATE); } retval = pam_start ("userdel", pampw->pw_name, &conv, &pamh); } if (PAM_SUCCESS == retval) { retval = pam_authenticate (pamh, 0); } if (PAM_SUCCESS == retval) { retval = pam_acct_mgmt (pamh, 0); } if (NULL != pamh) { (void) pam_end (pamh, retval); } if (PAM_SUCCESS != retval) { fprintf (stderr, _("%s: PAM authentication failed\n"), Prog); exit (E_PW_UPDATE); } #endif /* USE_PAM */ #endif /* ACCT_TOOLS_SETUID */ is_shadow_pwd = spw_file_present (); #ifdef SHADOWGRP is_shadow_grp = sgr_file_present (); #endif /* * Start with a quick check to see if the user exists. */ user_name = argv[argc - 1]; { struct passwd *pwd; pwd = getpwnam (user_name); /* local, no need for xgetpwnam */ if (NULL == pwd) { fprintf (stderr, _("%s: user '%s' does not exist\n"), Prog, user_name); #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user not found", user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif exit (E_NOTFOUND); } user_id = pwd->pw_uid; user_home = xstrdup (pwd->pw_dir); } #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 /* * Check to make certain the user isn't logged in. * Note: This is a best effort basis. The user may log in between, * a cron job may be started on her behalf, etc. */ if (user_busy (user_name, user_id) != 0) { fprintf (stderr, _("%s: user %s is currently logged in\n"), Prog, user_name); if (!fflg) { #ifdef WITH_AUDIT audit_logger (AUDIT_DEL_USER, Prog, "deleting user logged in", user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); #endif exit (E_USER_BUSY); } } /* * Do the hard stuff - open the files, create the user entries, * create the home directory, then close and update the files. */ open_files (); update_user (); update_groups (); if (rflg) { errors += remove_mailbox (); } if (rflg) { int home_owned = is_owner (user_id, user_home); if (-1 == home_owned) { fprintf (stderr, _("%s: %s home directory (%s) not found\n"), Prog, user_name, user_home); rflg = 0; } else if ((0 == home_owned) && !fflg) { fprintf (stderr, _("%s: %s not owned by %s, not removing\n"), Prog, user_home, user_name); rflg = 0; errors++; /* continue */ } } #ifdef EXTRA_CHECK_HOME_DIR /* This may be slow, the above should be good enough. */ if (rflg && !fflg) { struct passwd *pwd; /* * For safety, refuse to remove the home directory if it * would result in removing some other user's home * directory. Still not perfect so be careful, but should * prevent accidents if someone has /home or / as home * directory... --marekm */ setpwent (); while ((pwd = getpwent ())) { if (strcmp (pwd->pw_name, user_name) == 0) { continue; } if (path_prefix (user_home, pwd->pw_dir)) { fprintf (stderr, _ ("%s: not removing directory %s (would remove home of user %s)\n"), Prog, user_home, pwd->pw_name); rflg = false; errors++; /* continue */ break; } } endpwent (); } #endif if (rflg) { if (remove_tree (user_home) != 0) { fprintf (stderr, _("%s: error removing directory %s\n"), Prog, user_home); errors++; /* continue */ } #ifdef WITH_AUDIT else { audit_logger (AUDIT_DEL_USER, Prog, "deleting home directory", user_name, (unsigned int) user_id, SHADOW_AUDIT_SUCCESS); } #endif } #ifdef WITH_AUDIT if (0 != errors) { audit_logger (AUDIT_DEL_USER, Prog, "deleting home directory", user_name, AUDIT_NO_ID, SHADOW_AUDIT_FAILURE); } #endif #ifdef WITH_SELINUX if (is_selinux_enabled () > 0) { const char *args[5]; args[0] = "/usr/sbin/semanage"; args[1] = "login"; args[2] = "-d"; args[3] = user_name; args[4] = NULL; safe_system (args[0], args, NULL, 1); } #endif /* * Cancel any crontabs or at jobs. Have to do this before we remove * the entry from /etc/passwd. */ user_cancel (user_name); close_files (); nscd_flush_cache ("passwd"); nscd_flush_cache ("group"); return ((0 != errors) ? E_HOMEDIR : E_SUCCESS); }
int main(int argc, char **argv) { struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; bool rm_xdp_prog = false; struct passwd *pwd = NULL; __u32 xdp_flags = 0; char filename[256]; int longindex = 0; uid_t owner = -1; /* -1 result in no-change of owner */ gid_t group = -1; int opt; snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); /* Parse commands line args */ while ((opt = getopt_long(argc, argv, "hSrqd:", long_options, &longindex)) != -1) { switch (opt) { case 'q': verbose = 0; break; case 'r': rm_xdp_prog = true; break; case 'o': /* extract owner and group from username */ if (!(pwd = getpwnam(optarg))) { fprintf(stderr, "ERR: unknown owner:%s err(%d):%s\n", optarg, errno, strerror(errno)); goto error; } owner = pwd->pw_uid; group = pwd->pw_gid; break; case 'd': if (strlen(optarg) >= IF_NAMESIZE) { fprintf(stderr, "ERR: --dev name too long\n"); goto error; } ifname = (char *)&ifname_buf; strncpy(ifname, optarg, IF_NAMESIZE); ifindex = if_nametoindex(ifname); if (ifindex == 0) { fprintf(stderr, "ERR: --dev name unknown err(%d):%s\n", errno, strerror(errno)); goto error; } break; case 'S': xdp_flags |= XDP_FLAGS_SKB_MODE; break; case 'h': error: default: usage(argv); return EXIT_FAIL_OPTION; } } /* Required options */ if (ifindex == -1) { printf("ERR: required option --dev missing"); usage(argv); return EXIT_FAIL_OPTION; } if (rm_xdp_prog) { remove_xdp_program(ifindex, ifname, xdp_flags); return EXIT_OK; } if (verbose) { printf("Documentation:\n%s\n", __doc__); printf(" - Attached to device:%s (ifindex:%d)\n", ifname, ifindex); } /* Increase resource limits */ if (setrlimit(RLIMIT_MEMLOCK, &r)) { perror("setrlimit(RLIMIT_MEMLOCK, RLIM_INFINITY)"); return 1; } /* Load bpf-ELF file with callback for loading maps via filesystem */ if (load_bpf_file_fixup_map(filename, pre_load_maps_via_fs)) { fprintf(stderr, "ERR in load_bpf_file(): %s", bpf_log_buf); return EXIT_FAIL; } if (!prog_fd[0]) { printf("load_bpf_file: %s\n", strerror(errno)); return 1; } /* Export maps that were not loaded from filesystem */ export_maps(); if (owner >= 0) chown_maps(owner, group); if (set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) { printf("link set xdp fd failed\n"); return EXIT_FAIL_XDP; } /* Add something to the map as a test */ blacklist_modify(map_fd[0], "198.18.50.3", ACTION_ADD); blacklist_port_modify(map_fd[2], map_fd[4], 80, ACTION_ADD, IPPROTO_UDP); return EXIT_OK; }
/*===========================================================================* * sef_cb_init_fresh * *===========================================================================*/ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) { /* Initialize the inet server. */ int r; int timerand, fd; u8_t randbits[32]; struct timeval tv; struct passwd *pw; #if DEBUG printf("Starting inet...\n"); printf("%s\n", version); #endif #if HZ_DYNAMIC system_hz = sys_hz(); #endif /* Read configuration. */ nw_conf(); /* Get a random number */ timerand= 1; fd= open(RANDOM_DEV_NAME, O_RDONLY | O_NONBLOCK); if (fd != -1) { r= read(fd, randbits, sizeof(randbits)); if (r == sizeof(randbits)) timerand= 0; else { printf("inet: unable to read random data from %s: %s\n", RANDOM_DEV_NAME, r == -1 ? strerror(errno) : r == 0 ? "EOF" : "not enough data"); } close(fd); } else { printf("inet: unable to open random device %s: %s\n", RANDOM_DEV_NAME, strerror(errno)); } if (timerand) { printf("inet: using current time for random-number seed\n"); r= gettimeofday(&tv, NULL); if (r == -1) { printf("sysutime failed: %s\n", strerror(errno)); exit(1); } memcpy(randbits, &tv, sizeof(tv)); } init_rand256(randbits); /* Our new identity as a server. */ this_proc= info->endpoint; #ifdef BUF_CONSISTENCY_CHECK inet_buf_debug= (getenv("inetbufdebug") && (strcmp(getenv("inetbufdebug"), "on") == 0)); inet_buf_debug= 100; if (inet_buf_debug) { ip_warning(( "buffer consistency check enabled" )); } #endif if (getenv("killerinet")) { ip_warning(( "killer inet active" )); killer_inet= 1; } nw_init(); /* Subscribe to driver events for network drivers. */ r = ds_subscribe("drv\\.net\\..*", DSF_INITIAL | DSF_OVERWRITE); if(r != OK) { ip_panic(("inet: can't subscribe to driver events")); } /* Drop root privileges */ if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) { printf("inet: unable to retrieve uid of SERVICE_LOGIN, " "still running as root"); } else if (setuid(pw->pw_uid) != 0) { ip_panic(("inet: unable to drop privileges")); } /* Announce we are up. INET announces its presence to VFS just like * any other character driver. */ chardriver_announce(); return(OK); }
int packing_append_file_attr(struct packing *pack, const char *filepath, const char *newpath, const char *uname, const char *gname, mode_t perm) { int fd; char *map; int retcode = EPKG_OK; int ret; struct stat st; struct archive_entry *entry, *sparse_entry; bool unset_timestamp; entry = archive_entry_new(); archive_entry_copy_sourcepath(entry, filepath); pkg_debug(2, "Packing file '%s'", filepath); if (lstat(filepath, &st) != 0) { pkg_emit_errno("lstat", filepath); retcode = EPKG_FATAL; goto cleanup; } ret = archive_read_disk_entry_from_file(pack->aread, entry, -1, &st); if (ret != ARCHIVE_OK) { pkg_emit_error("%s: %s", filepath, archive_error_string(pack->aread)); retcode = EPKG_FATAL; goto cleanup; } if (newpath != NULL) archive_entry_set_pathname(entry, newpath); if (archive_entry_filetype(entry) != AE_IFREG) { archive_entry_set_size(entry, 0); } if (uname != NULL && uname[0] != '\0') { if (pack->pass) { struct passwd* pw = getpwnam(uname); if (pw == NULL) { pkg_emit_error("Unknown user: '******'", uname); retcode = EPKG_FATAL; goto cleanup; } archive_entry_set_uid(entry, pw->pw_uid); } archive_entry_set_uname(entry, uname); } if (gname != NULL && gname[0] != '\0') { if (pack->pass) { struct group *gr = (getgrnam(gname)); if (gr == NULL) { pkg_emit_error("Unknown group: '%s'", gname); retcode = EPKG_FATAL; goto cleanup; } archive_entry_set_gid(entry, gr->gr_gid); } archive_entry_set_gname(entry, gname); } if (perm != 0) archive_entry_set_perm(entry, perm); pkg_config_bool(PKG_CONFIG_UNSET_TIMESTAMP, &unset_timestamp); if (unset_timestamp) { archive_entry_unset_atime(entry); archive_entry_unset_ctime(entry); archive_entry_unset_mtime(entry); archive_entry_unset_birthtime(entry); } archive_entry_linkify(pack->resolver, &entry, &sparse_entry); if (sparse_entry != NULL && entry == NULL) entry = sparse_entry; archive_write_header(pack->awrite, entry); if (archive_entry_size(entry) > 0) { if ((fd = open(filepath, O_RDONLY)) < 0) { pkg_emit_errno("open", filepath); retcode = EPKG_FATAL; goto cleanup; } if (st.st_size > SSIZE_MAX) { char buf[BUFSIZ]; int len; while ((len = read(fd, buf, sizeof(buf))) > 0) if (archive_write_data(pack->awrite, buf, len) == -1) { pkg_emit_errno("archive_write_data", "archive write error"); retcode = EPKG_FATAL; break; } if (len == -1) { pkg_emit_errno("read", "file read error"); retcode = EPKG_FATAL; } close(fd); } else { if ((map = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { close(fd); if (archive_write_data(pack->awrite, map, st.st_size) == -1) { pkg_emit_errno("archive_write_data", "archive write error"); retcode = EPKG_FATAL; } munmap(map, st.st_size); } else { close(fd); pkg_emit_errno("open", filepath); retcode = EPKG_FATAL; goto cleanup; } } } cleanup: archive_entry_free(entry); return (retcode); }
/** daemonize, drop user priviliges and chroot if needed */ static void perform_setup(struct daemon* daemon, struct config_file* cfg, int debug_mode, const char** cfgfile) { #ifdef HAVE_KILL int pidinchroot; #endif #ifdef HAVE_GETPWNAM struct passwd *pwd = NULL; if(cfg->username && cfg->username[0]) { if((pwd = getpwnam(cfg->username)) == NULL) fatal_exit("user '%s' does not exist.", cfg->username); /* endpwent below, in case we need pwd for setusercontext */ } #endif #ifdef UB_ON_WINDOWS w_config_adjust_directory(cfg); #endif /* init syslog (as root) if needed, before daemonize, otherwise * a fork error could not be printed since daemonize closed stderr.*/ if(cfg->use_syslog) { log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); } /* if using a logfile, we cannot open it because the logfile would * be created with the wrong permissions, we cannot chown it because * we cannot chown system logfiles, so we do not open at all. * So, using a logfile, the user does not see errors unless -d is * given to unbound on the commandline. */ /* read ssl keys while superuser and outside chroot */ #ifdef HAVE_SSL if(!(daemon->rc = daemon_remote_create(cfg))) fatal_exit("could not set up remote-control"); if(cfg->ssl_service_key && cfg->ssl_service_key[0]) { if(!(daemon->listen_sslctx = listen_sslctx_create( cfg->ssl_service_key, cfg->ssl_service_pem, NULL))) fatal_exit("could not set up listen SSL_CTX"); } if(!(daemon->connect_sslctx = connect_sslctx_create(NULL, NULL, NULL))) fatal_exit("could not set up connect SSL_CTX"); #endif #ifdef HAVE_KILL /* true if pidfile is inside chrootdir, or nochroot */ pidinchroot = !(cfg->chrootdir && cfg->chrootdir[0]) || (cfg->chrootdir && cfg->chrootdir[0] && strncmp(cfg->pidfile, cfg->chrootdir, strlen(cfg->chrootdir))==0); /* check old pid file before forking */ if(cfg->pidfile && cfg->pidfile[0]) { /* calculate position of pidfile */ if(cfg->pidfile[0] == '/') daemon->pidfile = strdup(cfg->pidfile); else daemon->pidfile = fname_after_chroot(cfg->pidfile, cfg, 1); if(!daemon->pidfile) fatal_exit("pidfile alloc: out of memory"); checkoldpid(daemon->pidfile, pidinchroot); } #endif /* daemonize because pid is needed by the writepid func */ if(!debug_mode && cfg->do_daemonize) { detach(); } /* write new pidfile (while still root, so can be outside chroot) */ #ifdef HAVE_KILL if(cfg->pidfile && cfg->pidfile[0]) { writepid(daemon->pidfile, getpid()); if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1 && pidinchroot) { # ifdef HAVE_CHOWN if(chown(daemon->pidfile, cfg_uid, cfg_gid) == -1) { verbose(VERB_QUERY, "cannot chown %u.%u %s: %s", (unsigned)cfg_uid, (unsigned)cfg_gid, daemon->pidfile, strerror(errno)); } # endif /* HAVE_CHOWN */ } } #else (void)daemon; #endif /* HAVE_KILL */ /* Set user context */ #ifdef HAVE_GETPWNAM if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { #ifdef HAVE_SETUSERCONTEXT /* setusercontext does initgroups, setuid, setgid, and * also resource limits from login config, but we * still call setresuid, setresgid to be sure to set all uid*/ if(setusercontext(NULL, pwd, cfg_uid, (unsigned) LOGIN_SETALL & ~LOGIN_SETUSER & ~LOGIN_SETGROUP) != 0) log_warn("unable to setusercontext %s: %s", cfg->username, strerror(errno)); #endif /* HAVE_SETUSERCONTEXT */ } #endif /* HAVE_GETPWNAM */ /* box into the chroot */ #ifdef HAVE_CHROOT if(cfg->chrootdir && cfg->chrootdir[0]) { if(chdir(cfg->chrootdir)) { fatal_exit("unable to chdir to chroot %s: %s", cfg->chrootdir, strerror(errno)); } verbose(VERB_QUERY, "chdir to %s", cfg->chrootdir); if(chroot(cfg->chrootdir)) fatal_exit("unable to chroot to %s: %s", cfg->chrootdir, strerror(errno)); if(chdir("/")) fatal_exit("unable to chdir to / in chroot %s: %s", cfg->chrootdir, strerror(errno)); verbose(VERB_QUERY, "chroot to %s", cfg->chrootdir); if(strncmp(*cfgfile, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) (*cfgfile) += strlen(cfg->chrootdir); /* adjust stored pidfile for chroot */ if(daemon->pidfile && daemon->pidfile[0] && strncmp(daemon->pidfile, cfg->chrootdir, strlen(cfg->chrootdir))==0) { char* old = daemon->pidfile; daemon->pidfile = strdup(old+strlen(cfg->chrootdir)); free(old); if(!daemon->pidfile) log_err("out of memory in pidfile adjust"); } daemon->chroot = strdup(cfg->chrootdir); if(!daemon->chroot) log_err("out of memory in daemon chroot dir storage"); } #else (void)cfgfile; #endif /* change to working directory inside chroot */ if(cfg->directory && cfg->directory[0]) { char* dir = cfg->directory; if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(dir, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) dir += strlen(cfg->chrootdir); if(dir[0]) { if(chdir(dir)) { fatal_exit("Could not chdir to %s: %s", dir, strerror(errno)); } verbose(VERB_QUERY, "chdir to %s", dir); } } /* drop permissions after chroot, getpwnam, pidfile, syslog done*/ #ifdef HAVE_GETPWNAM if(cfg->username && cfg->username[0] && cfg_uid != (uid_t)-1) { # ifdef HAVE_INITGROUPS if(initgroups(cfg->username, cfg_gid) != 0) log_warn("unable to initgroups %s: %s", cfg->username, strerror(errno)); # endif /* HAVE_INITGROUPS */ # ifdef HAVE_ENDPWENT endpwent(); # endif #ifdef HAVE_SETRESGID if(setresgid(cfg_gid,cfg_gid,cfg_gid) != 0) #elif defined(HAVE_SETREGID) && !defined(DARWIN_BROKEN_SETREUID) if(setregid(cfg_gid,cfg_gid) != 0) #else /* use setgid */ if(setgid(cfg_gid) != 0) #endif /* HAVE_SETRESGID */ fatal_exit("unable to set group id of %s: %s", cfg->username, strerror(errno)); #ifdef HAVE_SETRESUID if(setresuid(cfg_uid,cfg_uid,cfg_uid) != 0) #elif defined(HAVE_SETREUID) && !defined(DARWIN_BROKEN_SETREUID) if(setreuid(cfg_uid,cfg_uid) != 0) #else /* use setuid */ if(setuid(cfg_uid) != 0) #endif /* HAVE_SETRESUID */ fatal_exit("unable to set user id of %s: %s", cfg->username, strerror(errno)); verbose(VERB_QUERY, "drop user privileges, run as %s", cfg->username); } #endif /* HAVE_GETPWNAM */ /* file logging inited after chroot,chdir,setuid is done so that * it would succeed on SIGHUP as well */ if(!cfg->use_syslog) log_init(cfg->logfile, cfg->use_syslog, cfg->chrootdir); }
/* * expand tilde from the passwd file. */ static const Char * globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) { struct passwd *pwd; char *h; const Char *p; Char *b, *eb; if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) return pattern; /* Copy up to the end of the string or / */ eb = &patbuf[patbuf_len - 1]; for (p = pattern + 1, h = (char *) patbuf; h < (char *)eb && *p && *p != SLASH; *h++ = *p++) ; *h = EOS; #if 0 if (h == (char *)eb) return what; #endif if (((char *) patbuf)[0] == EOS) { /* * handle a plain ~ or ~/ by expanding $HOME * first and then trying the password file */ #if 0 if (issetugid() != 0 || (h = getenv("HOME")) == NULL) { #endif if ((getuid() != geteuid()) || (h = getenv("HOME")) == NULL) { if ((pwd = getpwuid(getuid())) == NULL) return pattern; else h = pwd->pw_dir; } } else { /* * Expand a ~user */ if ((pwd = getpwnam((char*) patbuf)) == NULL) return pattern; else h = pwd->pw_dir; } /* Copy the home directory */ for (b = patbuf; b < eb && *h; *b++ = *h++) ; /* Append the rest of the pattern */ while (b < eb && (*b++ = *p++) != EOS) ; *b = EOS; return patbuf; } static int g_strncmp(const Char *s1, const char *s2, size_t n) { int rv = 0; while (n--) { rv = *(Char *)s1 - *(const unsigned char *)s2++; if (rv) break; if (*s1++ == '\0') break; } return rv; }
void Pass(char *param) { struct passwd *pw; struct spwd *spw; char *passwd, salt[13]; if (!input_user) { outs("%d Login with USER first.", ACK_503); return; } /* judge and chdir to its home directory */ if (!anonymous_login) { if (system_uid != 0) { outs("%d Login incorrect.", ACK_530); input_user = 0; return; } if ((pw = getpwnam(username)) == NULL) { outs("%d Login incorrect.", ACK_530); input_user = 0; return; } passwd = pw->pw_passwd; if (passwd == NULL || strcmp(passwd, "x") == 0) { spw = getspnam(username); if (spw == NULL || (passwd = spw->sp_pwdp) == NULL) { outs("%d Login incorrect.", ACK_530); input_user = 0; return; } } strncpy(salt, passwd, 12); if (strcmp(passwd, crypto((const char *)param, (const char *)salt)) != 0) { outs("%d Login incorrect.", ACK_530); input_user = 0; return; } strcpy(path, ""); setuid(pw->pw_uid); if (pw->pw_dir) strncpy(path, pw->pw_dir, PATH_MAX); else strcpy(path, "/"); outs("%d User %s logged in.", ACK_230, username); chdir(path); getcwd(path, PATH_MAX); user_valid = 1; } else { if ((pw = getpwuid(system_uid)) == NULL) { outs("%d Login incorrect.", ACK_530); input_user = 0; return; } if (pw->pw_dir) strncpy(basedir, pw->pw_dir, PATH_MAX); else strcpy(basedir, ""); strcpy(path, "/"); chdir(basedir); getcwd(basedir, PATH_MAX); user_valid = 1; outs("%d Anonymous access granted, restrictions apply.", ACK_230); } user_valid = 1; outs("%d Anonymous access granted, restrictions apply.", ACK_230); }
int main (int argc, char *argv[]) { const char *globfile[] = { "one", "two", "three", NULL }; char tmpdir[32]; struct passwd *pw; const char *cwd; int test; int fail = 0; int i; if (argc > 1) { command_line_test (argv[1]); return 0; } cwd = getcwd (NULL, 0); /* Set up arena for pathname expansion */ tmpnam (tmpdir); if (mkdir (tmpdir, S_IRWXU) || chdir (tmpdir)) return -1; else { int fd; for (i = 0; globfile[i]; ++i) if ((fd = creat (globfile[i], S_IRUSR | S_IWUSR)) == -1 || close (fd)) return -1; } for (test = 0; test_case[test].retval != -1; test++) if (testit (&test_case[test])) ++fail; pw = getpwnam ("root"); if (pw != NULL) { struct test_case_struct ts; ts.retval = 0; ts.env = NULL; ts.words = "~root"; ts.flags = 0; ts.wordc = 1; ts.wordv[0] = pw->pw_dir; ts.ifs = IFS; if (testit (&ts)) ++fail; } puts ("tests completed, now cleaning up"); /* Clean up */ for (i = 0; globfile[i]; ++i) remove (globfile[i]); if (cwd == NULL) cwd = ".."; chdir (cwd); rmdir (tmpdir); printf ("tests failed: %d\n", fail); return fail != 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 uid = 0, gid = 0; int agent_mode = -1; char *cptr, **argvptr; 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; } #ifdef WIN32 snmp_log_syslogname(app_name_long); #else snmp_log_syslogname(app_name); #endif 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': snmp_set_dump_packet(++snmp_dump_packet); netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_VERBOSE, 1); break; case 'D': debug_register_tokens(optarg); snmp_set_do_debugging(1); break; case 'f': dont_fork = 1; break; #if HAVE_UNISTD_H case 'g': if (optarg != NULL) { netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_GROUPID, atoi(optarg)); } 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; 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; 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': snmp_set_quick_print(1); break; case 'r': netsnmp_ds_toggle_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS); break; 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; 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 (*ecp) { #if HAVE_GETPWNAM && HAVE_PWD_H struct passwd *info; info = getpwnam(optarg); if (info) { uid = info->pw_uid; } else { #endif fprintf(stderr, "Bad user id: %s\n", optarg); exit(1); #if HAVE_GETPWNAM && HAVE_PWD_H } #endif } 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) { /* * 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 = 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))); } #ifdef NETSNMP_LOGFILE if (0 == log_set) snmp_enable_filelog(NETSNMP_LOGFILE, netsnmp_ds_get_boolean(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPEND_LOGFILES)); #endif /* * Initialize a argv set to the current for restarting the agent. */ 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]); if (agent_mode == -1) { if (strstr(argvrestartname, "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); } for (cptr = argvrestart, i = 0; i < argc; i++) { strcpy(cptr, argv[i]); *(argvptr++) = cptr; cptr += strlen(argv[i]) + 1; } *cptr = 0; *argvptr = NULL; #ifdef BUFSIZ setvbuf(stdout, NULL, _IOLBF, BUFSIZ); #endif /* * 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, snmp_stderrlog_status()); /* * xxx-rks: do we care if fork fails? I think we should... */ if(ret != 0) Exit(1); /* Exit logs exit val for us */ } SOCK_STARTUP; init_agent(app_name); /* do what we need to do first. */ init_mib_modules(); /* * start library */ init_snmp(app_name); if ((ret = init_master_agent()) != 0) { /* * Some error opening one of the specified agent transports. */ Exit(1); /* Exit logs exit val for us */ } #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); } close(fd); } } #endif #if HAVE_UNISTD_H cptr = get_persistent_directory(); mkdirhier( cptr, 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( cptr, 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) { 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); /* * 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); #ifdef SHUTDOWN_AGENT_CLEANLY /* broken code */ /* these attempt to free all known memory, but result in double frees */ shutdown_master_agent(); shutdown_agent(); #endif 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 SNMP_FREE(argvrestartname); SNMP_FREE(argvrestart); SNMP_FREE(argvrestartp); SOCK_CLEANUP; return 0; } /* End main() -- snmpd */
/******************************************************* * * Main function * *******************************************************/ int main(int argc, char *argv[]) { int auth_state = AUTH_NONE; char cryptobuf[SHA1KEYL*2]; char buf[256]; int i, res, nullfd; int sock, newsock; fd_set active_fd_set, read_fd_set; struct sockaddr_in clientaddr; size_t size; FILE *fd; /* previous balance and limit status */ int balance = 0, limit = 0; int opt; while ((opt = getopt(argc, argv, ":c:p:i:u:h")) != -1) { switch (opt) { case 'c': conf_name = optarg; break; case 'p': pid_name = optarg; break; case 'i': info_name = optarg; break; case 'u': user_name = optarg; break; case ':': log_err("wrong parameters"); case 'h': default: fprintf(stderr, "usage: %s [options]\n" "options:\n" " -c <conf_file>\n" " -p <pid_file>\n" " -c <info_file>\n" " -u <user_name>\n", DAEMON_NAME); exit(EXIT_FAILURE); } } if (!readconfig()) { sprintf(buf, "can't read configuration file %s: %s\n", conf_name, strerror(errno)); fprintf(stderr, buf); log_err(buf); exit (EXIT_FAILURE); } /* close standard I/O handles */ nullfd = open("/dev/null", O_RDWR); if (nullfd < 0) { perror("/dev/null"); } else { dup2(nullfd,0); dup2(nullfd,1); dup2(nullfd,2); close(nullfd); } if(fork()) { exit(EXIT_SUCCESS); } /* Daemon is started */ /* Create the socket and set it up to accept connections */ sock = make_socket(SERV_TCP_PORT); if (listen(sock, 3) < 0) { log_err("can't listen to main socket"); exit(EXIT_FAILURE); } /* Set stop signal */ signal(SIGINT, authcli_term); signal(SIGTERM, authcli_term); signal(SIGQUIT, authcli_term); /* Set SIGCHLD */ signal(SIGCHLD, authcli_child); /* Set SIGHUP */ signal(SIGHUP, authcli_hup); log_msg("%s v.%.2f started.", DAEMON_NAME, VERSION/100.); log_msg("listening on TCP port %d", SERV_TCP_PORT); /* Write PID file */ if (pid_name) { pid_t pid = getpid(); if (pid < 0) { log_err("can't get pid"); exit(EXIT_FAILURE); } fd = fopen(pid_name, "w"); if (fd != NULL) { fprintf(fd, "%d", pid); fclose(fd); } else log_err("can't create pid file %s: %s", pid_name, strerror(errno)); } /* Switch to unpriviledged account */ if (user_name) { struct passwd* ppwd; ppwd = getpwnam(user_name); if (ppwd) { log_dbg("switching to unprivileged user \'%s\' (UID %d, GID %d)", user_name, ppwd->pw_uid, ppwd->pw_gid); setuid(ppwd->pw_uid); setgid(ppwd->pw_gid); } else log_dbg("can't switch to unprivileged user \'%s\'", user_name); } child_pid = fork(); if (!child_pid) { sleep(1); // wait for parent network init request_auth_child(); exit(EXIT_SUCCESS); } /* Initialize the set of active sockets */ FD_ZERO(&active_fd_set); FD_SET(sock, &active_fd_set); while (loop_flag) { /* Block until input arrives on one or more active sockets */ read_fd_set = active_fd_set; if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) { log_dbg("select error: %s", strerror(errno)); continue; } /* Service all the sockets with input pending */ for (i = 0; i < FD_SETSIZE; i++) { if (FD_ISSET(i, &read_fd_set)) { if (i == sock) { /* New connection request on original socket. */ size = sizeof(clientaddr); if ((newsock = accept(sock, (struct sockaddr*)&clientaddr, (void*)&size)) < 0) { log_err("error accepting connection"); exit(EXIT_FAILURE); } pstrclientip = inet_ntoa(clientaddr.sin_addr); log_dbg("new connection from %s", pstrclientip); FD_SET(newsock, &active_fd_set); } else { /* Data arriving on an already-connected socket */ struct message mr, ms; log_dbg("receiving data"); memset((void*)&mr, 0, sizeof(mr)); // clear message structure before recv res = recv_message(i, &mr); if (res < 1) { if (res != 0) { #ifndef LOG_INVALID_MESSAGES log_err("error receiving auth message"); #endif } close(i); FD_CLR(i, &active_fd_set); continue; } if(mr.attr == A_KEYSND) { memset((void*)&ms, 0, sizeof(ms)); // clear send buffer ms.attr = a_passnd; a_passnd = A_PASSND2 | (AUTH_VERSION<<16); memcpy(cryptobuf, mr.challenge, SHA1KEYL); memcpy(cryptobuf+SHA1KEYL, NKEY, SHA1KEYL); sha1encode_strn((unsigned char*)cryptobuf, SHA1KEYL*2, ms.response); if (!send_message(i, &ms)) { #ifndef LOG_INVALID_MESSAGES log_msg("error sending auth message"); #endif close(i); FD_CLR(i, &active_fd_set); } continue; } else if (mr.attr == A_PASASQ) { int balance_cur, limit_cur; if (mr.auth.result == AUTH_ACCEPT) { balance_cur = mr.auth.balance; limit_cur = mr.auth.limit; /* log balance only if it has been changed or if this is the * first time we've got auth accept message */ if ((balance_cur != balance) || (limit_cur != limit) || (auth_state != AUTH_ACCEPT)) { /* dump info */ if (info_name) { fd = fopen(info_name, "w"); if (fd != NULL) { fprintf(fd, "BALANCE=%.2f\n" "LIMIT=%.2f\n", balance_cur/100., limit_cur/100.); fclose(fd); } else log_err("can't create info file %s: %s", info_name, strerror(errno)); } if (balance_cur < limit_cur) { log_msg("low balance %.2f",balance_cur/100.); } else { log_msg("balance %.2f",balance_cur/100.); } balance = balance_cur; limit = limit_cur; } if (auth_state != AUTH_ACCEPT) { log_msg("auth key accepted"); auth_state = AUTH_ACCEPT; } } } else if (mr.attr == A_PASNEG) { log_msg("invalid password"); auth_state = AUTH_REJECT; } else if (mr.attr == A_WRNVER) { log_msg("wrong client version"); } else if (auth_state != AUTH_REJECT) { log_msg("auth key rejected"); auth_state = AUTH_REJECT; } close(i); FD_CLR(i, &active_fd_set); } } /* end if */ } /* end for */ } /* end while */ /* Clean up pid and info files * Note: Take care of unprivileged user permissions */ if (info_name) unlink(info_name); if (pid_name) unlink(pid_name); return 0; }
int _SMERP_posixMain( int argc, char* argv[] ) { // i18n global stuff if ( setlocale( LC_ALL, "" ) == NULL ) { std::cerr << "Unable to set locale. Falling back to default." << std::endl; } else { if ( bindtextdomain( "SMERP", "../po" ) == NULL ) { std::cerr << "Not enough memory to bind textdomain" << std::endl; return _SMERP::ErrorCodes::FAILURE; } if ( textdomain( "SMERP" ) == NULL ) { std::cerr << "Not enough memory to set textdomain" << std::endl; return _SMERP::ErrorCodes::FAILURE; } } // end of i18n global stuff try { _SMERP::Version appVersion( MAJOR_VERSION, MINOR_VERSION, REVISION_NUMBER ); _SMERP::CmdLineConfig cmdLineCfg; const char *configFile; // it's just a DUMMY for now _SMERP::HandlerConfiguration handlerConfig; if ( !cmdLineCfg.parse( argc, argv )) { // there was an error parsing the command line std::cerr << cmdLineCfg.errMsg() << std::endl << std::endl; cmdLineCfg.usage( std::cerr ); std::cerr << std::endl; return _SMERP::ErrorCodes::FAILURE; } // command line has been parsed successfully // if cmdLineCfg.errMsg() is not empty than we have a warning if ( !cmdLineCfg.errMsg().empty() ) // there was a warning parsing the command line std::cerr << "BOO:" << cmdLineCfg.errMsg() << std::endl << std::endl; // if we have to print the version or the help do it and exit if ( cmdLineCfg.command == _SMERP::CmdLineConfig::PRINT_VERSION ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } if ( cmdLineCfg.command == _SMERP::CmdLineConfig::PRINT_HELP ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl; cmdLineCfg.usage( std::cout ); std::cout << std::endl; return _SMERP::ErrorCodes::OK; } // decide what configuration file to use if ( !cmdLineCfg.cfgFile.empty() ) // if it has been specified than that's The One ! (and only) configFile = cmdLineCfg.cfgFile.c_str(); else configFile = _SMERP::CfgFileConfig::chooseFile( DEFAULT_MAIN_CONFIG, DEFAULT_USER_CONFIG, DEFAULT_LOCAL_CONFIG ); if ( configFile == NULL ) { // there is no configuration file std::cerr << gettext ( "MOMOMO: no configuration file found !" ) << std::endl << std::endl; return _SMERP::ErrorCodes::FAILURE; } _SMERP::CfgFileConfig cfgFileCfg; if ( !cfgFileCfg.parse( configFile )) { // there was an error parsing the configuration file std::cerr << cfgFileCfg.errMsg() << std::endl << std::endl; return _SMERP::ErrorCodes::FAILURE; } else if ( !cfgFileCfg.errMsg().empty()) std::cerr << cfgFileCfg.errMsg() << std::endl; // configuration file has been parsed successfully // build the application configuration _SMERP::ApplicationConfiguration config( cmdLineCfg, cfgFileCfg); // now here we know where to log to on stderr _SMERP::LogBackend::instance().setConsoleLevel( config.stderrLogLevel ); // Check the configuration if ( cmdLineCfg.command == _SMERP::CmdLineConfig::CHECK_CONFIG ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl; if ( config.check() ) { if ( config.errMsg().empty() ) { std::cout << "Configuration OK" << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } else { std::cout << "WARNING: " << config.errMsg() << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } } else { std::cout << "ERROR: " << config.errMsg() << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } } if ( cmdLineCfg.command == _SMERP::CmdLineConfig::PRINT_CONFIG ) { std::cout << std::endl << gettext( "BOBOBO version " ) << appVersion.toString() << std::endl; config.print( std::cout ); std::cout << std::endl; return _SMERP::ErrorCodes::OK; } if ( cmdLineCfg.command == _SMERP::CmdLineConfig::TEST_CONFIG ) { std::cout << "Not implemented yet" << std::endl << std::endl; return _SMERP::ErrorCodes::OK; } // Daemon stuff if( !config.foreground ) { // Aba: maybe also in the foreground? // try to lock the pidfile, bail out if not possible if( boost::filesystem::exists( config.pidFile ) ) { boost::interprocess::file_lock lock( config.pidFile.c_str( ) ); if( lock.try_lock( ) ) { std::cerr << "Pidfile is locked, another daemon running?" << std::endl; return _SMERP::ErrorCodes::FAILURE; } } // daemonize, lose process group, terminal output, etc. if( daemon( 0, 0 ) ) { std::cerr << "Daemonizing server failed" << std::endl; return _SMERP::ErrorCodes::FAILURE; } // now here we lost constrol over the console, we should // create a temporary logger which at least tells what's // going on in the syslog _SMERP::LogBackend::instance().setSyslogLevel( config.syslogLogLevel ); _SMERP::LogBackend::instance().setSyslogFacility( config.syslogFacility ); _SMERP::LogBackend::instance().setSyslogIdent( config.syslogIdent ); // if we are root we can drop privileges now struct group *groupent; struct passwd *passwdent; groupent = getgrnam( config.group.c_str( ) ); passwdent = getpwnam( config.user.c_str( ) ); if( groupent == NULL || passwdent == NULL ) { LOG_CRITICAL << "Illegal group '" << config.group << "' or user '" << config.user << "'"; return _SMERP::ErrorCodes::FAILURE; } if( setgid( groupent->gr_gid ) < 0 ) { LOG_CRITICAL << "setgid for group '" << config.group << "' failed!"; return _SMERP::ErrorCodes::FAILURE; } if( setuid( passwdent->pw_uid ) < 0 ) { LOG_CRITICAL << "setgid for user '" << config.user << "' failed!"; return _SMERP::ErrorCodes::FAILURE; } // create a pid file and lock id std::ofstream pidFile( config.pidFile.c_str( ), std::ios_base::trunc ); if( !pidFile.good( ) ) { LOG_CRITICAL << "Unable to create PID file '" << config.pidFile << "'!"; return _SMERP::ErrorCodes::FAILURE; } pidFile << getpid( ) << std::endl; pidFile.close( ); // Create the final logger based on the configuration // file logger only here to get the right permissions _SMERP::LogBackend::instance().setLogfileLevel( config.logFileLogLevel ); _SMERP::LogBackend::instance().setLogfileName( config.logFile ); } // Block all signals for background thread. sigset_t new_mask; sigfillset( &new_mask ); sigset_t old_mask; pthread_sigmask( SIG_BLOCK, &new_mask, &old_mask ); LOG_NOTICE << "Starting server"; // Run server in background thread(s). _SMERP::ServerHandler handler( handlerConfig ); _SMERP::Network::server s( config.address, config.SSLaddress, handler, config.threads, config.maxConnections ); boost::thread t( boost::bind( &_SMERP::Network::server::run, &s )); // Restore previous signals. pthread_sigmask( SIG_SETMASK, &old_mask, 0 ); // Wait for signal indicating time to shut down. sigset_t wait_mask; sigemptyset( &wait_mask ); sigaddset( &wait_mask, SIGINT ); sigaddset( &wait_mask, SIGQUIT ); sigaddset( &wait_mask, SIGTERM ); pthread_sigmask( SIG_BLOCK, &wait_mask, 0 ); int sig = 0; sigwait( &wait_mask, &sig ); // Stop the server. LOG_INFO << "Stopping server"; s.stop(); t.join(); LOG_NOTICE << "Server stopped"; // Daemon stuff if( !config.foreground ) { (void)remove( config.pidFile.c_str( ) ); } } catch (std::exception& e) { // Aba: how to delete the pid file here? LOG_ERROR << "posixMain: exception: " << e.what() << "\n"; return _SMERP::ErrorCodes::FAILURE; } return _SMERP::ErrorCodes::OK; }
void SettingsParseCommandLine(int argc, char *argv[]) { int i; if (argc < 2) return; if (strcmp("-user", argv[1])==0) SettingsParseUserCommandLine(argc, argv); else { for (i=1; i < argc; i++) { if (strcmp("-?",argv[i])==0) SettingsPrintUsage(); else if (strcmp("-help",argv[i])==0) SettingsPrintUsage(); else if (strcmp("--help",argv[i])==0) SettingsPrintUsage(); else if (strcmp("-version",argv[i])==0) PrintVersion(); else if (strcmp("--version",argv[i])==0) PrintVersion(); else if (strcmp("-chroot",argv[i])==0) { Settings.Flags |= FLAG_CHROOT; Settings.ChDir=CopyStr(Settings.ChDir,argv[++i]); } else if (strcmp("-dynhome",argv[i])==0) { Settings.Flags |= FLAG_DYNHOME | FLAG_UNMOUNT; Settings.DynamicHomeDir=CopyStr(Settings.DynamicHomeDir,argv[++i]); } else if (strcmp("-debug", argv[i])==0) Settings.Flags |= FLAG_DEBUG; else if (strcmp("-honeypot", argv[i])==0) { Settings.Flags |= FLAG_DENYAUTH | FLAG_HONEYPOT; Settings.AuthMethods=CopyStr(Settings.AuthMethods,""); Settings.AuthFile=CopyStr(Settings.AuthFile,""); Settings.InfoLogLevel=LOG_CRIT; Settings.ErrorLogLevel=LOG_CRIT; } else if (strcmp("-chhome", argv[i])==0) Settings.Flags |= FLAG_CHHOME; else if (strcmp("-banner", argv[i])==0) Settings.Banner=CopyStr(Settings.Banner,argv[++i]); else if (strcmp("-env", argv[i])==0) Settings.Environment=CopyStr(Settings.Environment,argv[++i]); else if (strcmp("-a", argv[i])==0) Settings.AuthFile=CopyStr(Settings.AuthFile,argv[++i]); else if (strcmp("-A", argv[i])==0) Settings.AuthMethods=CopyStr(Settings.AuthMethods,argv[++i]); else if (strcmp("-auth-methods", argv[i])==0) Settings.AuthMethods=CopyStr(Settings.AuthMethods,argv[++i]); else if (strcmp("-auth-file", argv[i])==0) Settings.AuthFile=CopyStr(Settings.AuthFile,argv[++i]); else if (strcmp("-pid-file", argv[i])==0) Settings.PidFile=CopyStr(Settings.PidFile,argv[++i]); else if (strcmp("-auth-tries", argv[i])==0) Settings.AuthTries=atoi(argv[++i]); else if (strcmp("-auth-delay", argv[i])==0) Settings.AuthDelay=atoi(argv[++i]); else if (strcmp("-allow", argv[i])==0) Settings.AllowUsers=CopyStr(Settings.AllowUsers,argv[++i]); else if (strcmp("-deny", argv[i])==0) Settings.DenyUsers=CopyStr(Settings.DenyUsers,argv[++i]); else if (strcmp("-allow-users", argv[i])==0) Settings.AllowUsers=CopyStr(Settings.AllowUsers,argv[++i]); else if (strcmp("-deny-users", argv[i])==0) Settings.DenyUsers=CopyStr(Settings.DenyUsers,argv[++i]); else if (strcmp("-allow-ips", argv[i])==0) Settings.AllowIPs=CopyStr(Settings.AllowIPs,argv[++i]); else if (strcmp("-deny-ips", argv[i])==0) Settings.DenyIPs=CopyStr(Settings.DenyIPs,argv[++i]); else if (strcmp("-allow-macs", argv[i])==0) Settings.AllowMACs=CopyStr(Settings.AllowMACs,argv[++i]); else if (strcmp("-deny-macs", argv[i])==0) Settings.DenyMACs=CopyStr(Settings.DenyMACs,argv[++i]); else if (strcmp("-local", argv[i])==0) Settings.Flags |= FLAG_LOCALONLY; else if (strcmp("-m", argv[i])==0) Settings.BindMounts=CopyStr(Settings.BindMounts,argv[++i]); else if (strcmp("-mounts", argv[i])==0) Settings.BindMounts=CopyStr(Settings.BindMounts,argv[++i]); else if (strcmp("-i", argv[i])==0) Settings.Interface=CopyStr(Settings.Interface,argv[++i]); else if (strcmp("-p", argv[i])==0) Settings.Port=atoi(argv[++i]); else if (strcmp("-port", argv[i])==0) Settings.Port=atoi(argv[++i]); else if (strcmp("-inetd", argv[i])==0) Settings.Flags |= FLAG_INETD; else if (strcmp("-D", argv[i])==0) Settings.Flags |= FLAG_NODEMON; else if (strcmp("-nodemon", argv[i])==0) Settings.Flags |= FLAG_NODEMON; else if (strcmp("-idle", argv[i])==0) Settings.IdleTimeout=atoi(argv[++i]); else if (strcmp("-shell", argv[i])==0) { Settings.DefaultShell=CopyStr(Settings.DefaultShell,argv[++i]); Settings.Flags |= FLAG_FORCE_SHELL; } else if (strcmp("-error-log-level", argv[i])==0) Settings.ErrorLogLevel=SettingsParseLogLevel(argv[++i]); else if (strcmp("-info-log-level", argv[i])==0) Settings.InfoLogLevel=SettingsParseLogLevel(argv[++i]); else if (strcmp("-shell", argv[i])==0) Settings.DefaultShell=CopyStr(Settings.DefaultShell,argv[++i]); else if (strcmp("-login-script", argv[i])==0) Settings.LoginScript=CopyStr(Settings.LoginScript,argv[++i]); else if (strcmp("-logout-script", argv[i])==0) Settings.LogoutScript=CopyStr(Settings.LogoutScript,argv[++i]); else if (strcmp("-real-user", argv[i])==0) { i++; if (getpwnam(argv[i])) Settings.RealUser=CopyStr(Settings.RealUser,argv[i]); else { printf("ERROR: No such user: %s\n",argv[i]); exit(1); } Settings.Flags |= FLAG_FORCE_REALUSER; } else { printf("ERROR: Unknown option '%s'\n",argv[i]); Settings.Flags |= FLAG_ERROR; } } } if (Settings.Flags & FLAG_ERROR) { printf("%s -? for help\n",argv[0]); exit(1); } }
static char * ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_core_conf_t *ccf = conf; ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); ngx_conf_init_msec_value(ccf->timer_resolution, 0); ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); #if (NGX_HAVE_CPU_AFFINITY) if (ccf->cpu_affinity_n && ccf->cpu_affinity_n != 1 && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes) { ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "the number of \"worker_processes\" is not equal to " "the number of \"worker_cpu_affinity\" masks, " "using last mask for remaining worker processes"); } #endif if (ccf->pid.len == 0) { ngx_str_set(&ccf->pid, NGX_PID_PATH); } if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) { return NGX_CONF_ERROR; } ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT); ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len); if (ccf->oldpid.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len), NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT)); #if !(NGX_WIN32) if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) { struct group *grp; struct passwd *pwd; ngx_set_errno(0); pwd = getpwnam(NGX_USER); if (pwd == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getpwnam(\"" NGX_USER "\") failed"); return NGX_CONF_ERROR; } ccf->username = NGX_USER; ccf->user = pwd->pw_uid; ngx_set_errno(0); grp = getgrnam(NGX_GROUP); if (grp == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "getgrnam(\"" NGX_GROUP "\") failed"); return NGX_CONF_ERROR; } ccf->group = grp->gr_gid; } if (ccf->lock_file.len == 0) { ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH); } if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) { return NGX_CONF_ERROR; } { ngx_str_t lock_file; lock_file = cycle->old_cycle->lock_file; if (lock_file.len) { lock_file.len--; if (ccf->lock_file.len != lock_file.len || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len) != 0) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "\"lock_file\" could not be changed, ignored"); } cycle->lock_file.len = lock_file.len + 1; lock_file.len += sizeof(".accept"); cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } } else { cycle->lock_file.len = ccf->lock_file.len + 1; cycle->lock_file.data = ngx_pnalloc(cycle->pool, ccf->lock_file.len + sizeof(".accept")); if (cycle->lock_file.data == NULL) { return NGX_CONF_ERROR; } ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data, ccf->lock_file.len), ".accept", sizeof(".accept")); } } #endif return NGX_CONF_OK; }
static void daemonize (const char *lockfile, char *tty, char *name) { pid_t pid, sid, parent; int lfp = -1; FILE * pFile; char const *pidprefix = "/var/run/"; char const *pidsuffix = ".pid"; char pidfile[PIDFILE_LENGTH]; snprintf(pidfile, PIDFILE_LENGTH, "%s%s-%s%s", pidprefix, DAEMON_NAME, tty, pidsuffix); /* already a daemon */ if (getppid () == 1) return; /* Create the lock file as the current user */ if (lockfile && lockfile[0]) { lfp = open (lockfile, O_RDWR | O_CREAT, 0640); if (lfp < 0) { syslog (LOG_ERR, "unable to create lock file %s, code=%d (%s)", lockfile, errno, strerror (errno)); exit (EXIT_FAILURE); } } /* Drop user if there is one, and we were run as root */ if (getuid () == 0 || geteuid () == 0) { struct passwd *pw = getpwnam (RUN_AS_USER); if (pw) { //syslog (LOG_NOTICE, "setting user to " RUN_AS_USER); setuid (pw->pw_uid); } } /* Trap signals that we expect to receive */ signal (SIGCHLD, child_handler); signal (SIGUSR1, child_handler); signal (SIGALRM, child_handler); /* Fork off the parent process */ pid = fork (); if (pid < 0) { syslog (LOG_ERR, "unable to fork daemon, code=%d (%s)", errno, strerror (errno)); exit (EXIT_FAILURE); } /* If we got a good PID, then we can exit the parent process. */ if (pid > 0) { /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or for two seconds to elapse (SIGALRM). pause() should not return. */ alarm (2); pause (); exit (EXIT_FAILURE); } /* At this point we are executing as the child process */ parent = getppid (); /* Cancel certain signals */ signal (SIGCHLD, SIG_DFL); /* A child process dies */ signal (SIGTSTP, SIG_IGN); /* Various TTY signals */ signal (SIGTTOU, SIG_IGN); signal (SIGTTIN, SIG_IGN); signal (SIGHUP, SIG_IGN); /* Ignore hangup signal */ signal (SIGTERM, SIG_DFL); /* Die on SIGTERM */ /* Change the file mode mask */ umask (0); /* Create a new SID for the child process */ sid = setsid (); if (sid < 0) { syslog (LOG_ERR, "unable to create a new session, code %d (%s)", errno, strerror (errno)); exit (EXIT_FAILURE); } pFile = fopen (pidfile,"w"); if (pFile < 0) { syslog (LOG_ERR, "unable to create pid file %s, code=%d (%s)", pidfile, errno, strerror (errno)); exit (EXIT_FAILURE); } fprintf (pFile, "%d\n", sid); fclose (pFile); /* Change the current working directory. This prevents the current directory from being locked; hence not being able to remove it. */ if ((chdir ("/")) < 0) { syslog (LOG_ERR, "unable to change directory to %s, code %d (%s)", "/", errno, strerror (errno)); exit (EXIT_FAILURE); } /* Redirect standard files to /dev/null */ freopen ("/dev/null", "r", stdin); freopen ("/dev/null", "w", stdout); freopen ("/dev/null", "w", stderr); /* Tell the parent process that we are A-okay */ kill (parent, SIGUSR1); }
int main(int argc, char* argv[], char* envp[]) { if(argc < 7) usage(argv); char* root = argv[1]; char* thumbnail_root = argv[2]; char* listen_addr = argv[3]; num_workers = atoi(argv[6]); if(num_workers < 1) usage(argv); struct passwd* pwd = getpwnam(argv[4]); if (pwd == NULL) error_errno("getpwnam_r failed", EXIT_FAILURE); struct group* grp = getgrnam(argv[5]); if (grp == NULL) error_errno("getgrnam_r failed", EXIT_FAILURE); int userid = pwd->pw_uid; int groupid = grp->gr_gid; if(root[strlen(root) - 1] != '/' || thumbnail_root[strlen(thumbnail_root) - 1] != '/') error("Did you forget the ending slash in the (thumbnail) root directory path?", EXIT_FAILURE); // TODO Some more error checking // Initialize syslog syslog(LOG_INFO, "Starting up\n"); #if defined(DEBUG) setlogmask(LOG_UPTO(LOG_DEBUG)); openlog("fastresize", LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER); #else setlogmask(LOG_UPTO(LOG_INFO)); openlog("fastresize", LOG_CONS, LOG_USER); #endif // Change the working directory if((chdir(root)) < 0) error("Couldn't change working directory\n", EXIT_FAILURE); // Initialize FastCGI syslog(LOG_INFO, "Initializing FastCGI\n"); if(FCGX_Init()) error("Could not initialize FastCGI (during FCGX_Init())", EXIT_FAILURE); int listen_socket = FCGX_OpenSocket(listen_addr, 400); if(listen_socket < 0) error("Couldn't bind to FastCGI socket", EXIT_FAILURE); // Now that we've got our socket, drop root privileges if (getuid() == 0) { if (setgid(groupid) != 0) error_errno("setgid: Unable to drop group privileges", EXIT_FAILURE); if (setuid(userid) != 0) error_errno("setuid: Unable to drop user privileges", EXIT_FAILURE); } FCGX_Request request; if(FCGX_InitRequest(&request, listen_socket, 0)) error("Couldn't initialize FastCGI request handler", EXIT_FAILURE); // Initialize ImageMagick syslog(LOG_INFO, "Initializing ImageMagick\n"); MagickWandGenesis(); atexit(MagickWandTerminus); /* Fork a new master process to daemonize and exit the old one. We use * _Exit here to not trigger the atexit that terminates ImageMagick. */ if(fork()) _Exit(EXIT_SUCCESS); // Fork worker processes syslog(LOG_INFO, "Forking workers\n"); worker_pids = calloc(num_workers, sizeof(pid_t)); if(!worker_pids) error_errno("worker_pids: Could not allocate", 1); for(worker_id = 0; worker_id <= num_workers; worker_id++) { worker_pids[worker_id] = fork(); // Exit the loop if we're the forked process if(worker_pids[worker_id] == 0) break; syslog(LOG_INFO, "Forked worker with PID %d\n", worker_pids[worker_id]); } // The following code is only executed in the master process. if(worker_id > num_workers) { syslog(LOG_INFO, "master (PID %d): Sleeping until I receive a signal.\n", getpid()); /* Sleep a little until we get a SIG{TERM,HUP,INT} or one of our * workers died (not cool). */ struct sigaction exit_action; exit_action.sa_handler = &exit_signal; exit_action.sa_sigaction = &exit_signal; struct sigaction worker_died_action; worker_died_action.sa_handler = &worker_died; worker_died_action.sa_sigaction = &worker_died; sigaction(SIGTERM, &exit_action, NULL); sigaction(SIGHUP, &exit_action, NULL); sigaction(SIGINT, &exit_action, NULL); sigaction(SIGCHLD, &worker_died_action, NULL); pause(); // This should never™ be reached unless something funny happens. exit(EXIT_FAILURE); } syslog(LOG_INFO, "Worker #%d is now listening for requests on 127.0.0.1:9000\n", worker_id); while(FCGX_Accept_r(&request) == 0) handle_request(&request, root, thumbnail_root); // Exit exit(EXIT_SUCCESS); }
static void cups_finalize_client_conf( _cups_client_conf_t *cc) /* I - client.conf values */ { const char *value; /* Environment variable */ if ((value = getenv("CUPS_TRUSTFIRST")) != NULL) cc->trust_first = cups_boolean_value(value); if ((value = getenv("CUPS_ANYROOT")) != NULL) cc->any_root = cups_boolean_value(value); if ((value = getenv("CUPS_ENCRYPTION")) != NULL) cups_set_encryption(cc, value); if ((value = getenv("CUPS_EXPIREDCERTS")) != NULL) cc->expired_certs = cups_boolean_value(value); #ifdef HAVE_GSSAPI if ((value = getenv("CUPS_GSSSERVICENAME")) != NULL) cups_set_gss_service_name(cc, value); #endif /* HAVE_GSSAPI */ if ((value = getenv("CUPS_SERVER")) != NULL) cups_set_server_name(cc, value); if ((value = getenv("CUPS_USER")) != NULL) cups_set_user(cc, value); if ((value = getenv("CUPS_VALIDATECERTS")) != NULL) cc->validate_certs = cups_boolean_value(value); /* * Then apply defaults for those values that haven't been set... */ if (cc->trust_first < 0) cc->trust_first = 1; if (cc->any_root < 0) cc->any_root = 1; if (cc->encryption == (http_encryption_t)-1) cc->encryption = HTTP_ENCRYPTION_IF_REQUESTED; if (cc->expired_certs < 0) cc->expired_certs = 0; #ifdef HAVE_GSSAPI if (!cc->gss_service_name[0]) cups_set_gss_service_name(cc, CUPS_DEFAULT_GSSSERVICENAME); #endif /* HAVE_GSSAPI */ if (!cc->server_name[0]) { #ifdef CUPS_DEFAULT_DOMAINSOCKET /* * If we are compiled with domain socket support, only use the * domain socket if it exists and has the right permissions... */ if (!access(CUPS_DEFAULT_DOMAINSOCKET, R_OK)) cups_set_server_name(cc, CUPS_DEFAULT_DOMAINSOCKET); else #endif /* CUPS_DEFAULT_DOMAINSOCKET */ cups_set_server_name(cc, "localhost"); } if (!cc->user[0]) { #ifdef WIN32 /* * Get the current user name from the OS... */ DWORD size; /* Size of string */ size = sizeof(cc->user); if (!GetUserName(cc->user, &size)) #else /* * Try the USER environment variable as the default username... */ const char *envuser = getenv("USER"); /* Default username */ struct passwd *pw = NULL; /* Account information */ if (envuser) { /* * Validate USER matches the current UID, otherwise don't allow it to * override things... This makes sure that printing after doing su * or sudo records the correct username. */ if ((pw = getpwnam(envuser)) != NULL && pw->pw_uid != getuid()) pw = NULL; } if (!pw) pw = getpwuid(getuid()); if (pw) strlcpy(cc->user, pw->pw_name, sizeof(cc->user)); else #endif /* WIN32 */ { /* * Use the default "unknown" user name... */ strlcpy(cc->user, "unknown", sizeof(cc->user)); } } if (cc->validate_certs < 0) cc->validate_certs = 0; }
static void get_service_attr(PIPE_ATTR *attr, char **argv) { const char *myname = "get_service_attr"; struct passwd *pwd; struct group *grp; char *user; /* user name */ char *group; /* group name */ char *size; /* max message size */ char *cp; /* * Initialize. */ user = 0; group = 0; attr->command = 0; attr->flags = 0; attr->exec_dir = 0; attr->chroot_dir = 0; attr->eol = vstring_strcpy(vstring_alloc(1), "\n"); attr->null_sender = vstring_strcpy(vstring_alloc(1), MAIL_ADDR_MAIL_DAEMON); attr->size_limit = 0; /* * Iterate over the command-line attribute list. */ for ( /* void */ ; *argv != 0; argv++) { /* * flags=stuff */ if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) { for (cp = *argv + sizeof("flags=") - 1; *cp; cp++) { switch (*cp) { case 'B': attr->flags |= MAIL_COPY_BLANK; break; case 'D': attr->flags |= MAIL_COPY_DELIVERED; break; case 'F': attr->flags |= MAIL_COPY_FROM; break; case 'O': attr->flags |= MAIL_COPY_ORIG_RCPT; break; case 'R': attr->flags |= MAIL_COPY_RETURN_PATH; break; case 'X': attr->flags |= PIPE_OPT_FINAL_DELIVERY; break; case '.': attr->flags |= MAIL_COPY_DOT; break; case '>': attr->flags |= MAIL_COPY_QUOTE; break; case 'h': attr->flags |= PIPE_OPT_FOLD_HOST; break; case 'q': attr->flags |= PIPE_OPT_QUOTE_LOCAL; break; case 'u': attr->flags |= PIPE_OPT_FOLD_USER; break; default: msg_fatal("unknown flag: %c (ignored)", *cp); break; } } } /* * user=username[:groupname] */ else if (strncasecmp("user="******"user="******"user="******"%s: unknown username: %s", myname, user); attr->uid = pwd->pw_uid; if (group != 0) { if ((grp = getgrnam(group)) == 0) msg_fatal("%s: unknown group: %s", myname, group); attr->gid = grp->gr_gid; } else { attr->gid = pwd->pw_gid; } } /* * directory=string */ else if (strncasecmp("directory=", *argv, sizeof("directory=") - 1) == 0) { attr->exec_dir = mystrdup(*argv + sizeof("directory=") - 1); } /* * chroot=string */ else if (strncasecmp("chroot=", *argv, sizeof("chroot=") - 1) == 0) { attr->chroot_dir = mystrdup(*argv + sizeof("chroot=") - 1); } /* * eol=string */ else if (strncasecmp("eol=", *argv, sizeof("eol=") - 1) == 0) { unescape(attr->eol, *argv + sizeof("eol=") - 1); } /* * null_sender=string */ else if (strncasecmp("null_sender=", *argv, sizeof("null_sender=") - 1) == 0) { vstring_strcpy(attr->null_sender, *argv + sizeof("null_sender=") - 1); } /* * size=max_message_size (in bytes) */ else if (strncasecmp("size=", *argv, sizeof("size=") - 1) == 0) { size = *argv + sizeof("size=") - 1; if ((attr->size_limit = off_cvt_string(size)) < 0) msg_fatal("%s: bad size= value: %s", myname, size); } /* * argv=command... */ else if (strncasecmp("argv=", *argv, sizeof("argv=") - 1) == 0) { *argv += sizeof("argv=") - 1; /* XXX clobbers argv */ attr->command = argv; break; } /* * Bad. */ else msg_fatal("unknown attribute name: %s", *argv); } /* * Sanity checks. Verify that every member has an acceptable value. */ if (user == 0) msg_fatal("missing user= command-line attribute"); if (attr->command == 0) msg_fatal("missing argv= command-line attribute"); if (attr->uid == 0) msg_fatal("user= command-line attribute specifies root privileges"); if (attr->uid == var_owner_uid) msg_fatal("user= command-line attribute specifies mail system owner %s", var_mail_owner); if (attr->gid == 0) msg_fatal("user= command-line attribute specifies privileged group id 0"); if (attr->gid == var_owner_gid) msg_fatal("user= command-line attribute specifies mail system owner %s group id %ld", var_mail_owner, (long) attr->gid); if (attr->gid == var_sgid_gid) msg_fatal("user= command-line attribute specifies mail system %s group id %ld", var_sgid_group, (long) attr->gid); /* * Give the poor tester a clue of what is going on. */ if (msg_verbose) msg_info("%s: uid %ld, gid %ld, flags %d, size %ld", myname, (long) attr->uid, (long) attr->gid, attr->flags, (long) attr->size_limit); }
void edit_value(int curr) { struct passwd *pw = NULL; char ctdluidname[256]; char buf[SIZ]; char *default_value = NULL; int ctdluid = 0; int portnum = 0; int auth = 0; int lportnum = 0; if (setup_type == UI_SILENT) { default_value = getenv(EnvNames[curr]); } if (default_value == NULL) { default_value = ""; } switch (curr) { case eSysAdminName: getconf_str(admin_name, "c_sysadm"); set_str_val(curr, admin_name, default_value); setconf_str("c_sysadm", admin_name); break; case eSysAdminPW: set_str_val(curr, admin_pass, default_value); break; case eUID: if (setup_type == UI_SILENT) { if (default_value) { ctdluid = atoi(default_value); } } else { #ifdef __CYGWIN__ ctdluid = 0; /* work-around for Windows */ #else pw = getpwuid(ctdluid); if (pw == NULL) { set_int_val(curr, &ctdluid, default_value); } else { strcpy(ctdluidname, pw->pw_name); set_str_val(curr, ctdluidname, default_value); pw = getpwnam(ctdluidname); if (pw != NULL) { ctdluid = pw->pw_uid; } else if (atoi(ctdluidname) > 0) { ctdluid = atoi(ctdluidname); } } #endif } setconf_int("c_ctdluid", ctdluid); break; case eIP_ADDR: getconf_str(buf, "c_ip_addr"); set_str_val(curr, buf, default_value); setconf_str("c_ip_addr", buf); break; case eCTDL_Port: portnum = getconf_int("c_port_number"); set_int_val(curr, &portnum, default_value); setconf_int("c_port_number", portnum); break; case eAuthType: auth = getconf_int("c_auth_mode"); if (setup_type == UI_SILENT) { if ( (default_value) && (!strcasecmp(default_value, "yes")) ) auth = AUTHMODE_HOST; if ( (default_value) && (!strcasecmp(default_value, "host")) ) auth = AUTHMODE_HOST; if ( (default_value) && (!strcasecmp(default_value, "ldap")) ) auth = AUTHMODE_LDAP; if ( (default_value) && (!strcasecmp(default_value, "ldap_ad")) ) auth = AUTHMODE_LDAP_AD; if ( (default_value) && (!strcasecmp(default_value, "active directory")) ) auth = AUTHMODE_LDAP_AD; } else { set_int_val(curr, &auth, default_value); } setconf_int("c_auth_mode", auth); break; case eLDAP_Host: getconf_str(buf, "c_ldap_host"); if (IsEmptyStr(buf)) { strcpy(buf, "localhost"); } set_str_val(curr, buf, default_value); setconf_str("c_ldap_host", buf); break; case eLDAP_Port: lportnum = getconf_int("c_ldap_port"); if (lportnum == 0) { lportnum = 389; } set_int_val(curr, &lportnum, default_value); setconf_int("c_ldap_port", lportnum); break; case eLDAP_Base_DN: getconf_str(buf, "c_ldap_base_dn"); set_str_val(curr, buf, default_value); setconf_str("c_ldap_base_dn", buf); break; case eLDAP_Bind_DN: getconf_str(buf, "c_ldap_bind_dn"); set_str_val(curr, buf, default_value); setconf_str("c_ldap_bind_dn", buf); break; case eLDAP_Bind_PW: getconf_str(buf, "c_ldap_bind_pw"); set_str_val(curr, buf, default_value); setconf_str("c_ldap_bind_pw", buf); break; } }
static DEFPORT(WhoPort) { char *argv[] = {"/usr/tycho/sys/userlist", NULL}; int fd[2]; char *p; FILE *fp; char **list; char *item; SELECT opts = (SELECT)vu->vuoptions; static char buf[18]; char lbuf[128]; VU child; int pid; char *oldstat; int oldcolor; switch(event) { case VU_DESTROY: list = (char **)vu->vupaint; while(*list) free(*(list++)); free(vu->vupaint); break; case VU_BUTTON: list = (char **)vu->vupaint; strncpy(buf, list[opts->sel_mark], 16); buf[17] = 0; strtok(buf, " "); child = NULL; switch(p1) { case VU_MESSAGE: child = VUCreateQ(SendNotice, NULL, -1, -1, buf); break; case VU_FINGER: if(!strchr(buf, '@')) child = finger(getpwnam(buf)); else child = netfinger(buf); endpwent(); break; } if(child) { child->vuparent = vu->vuparent; vu->vuparent = child; } break; case VU_CREATE: oldstat = (char *)front->vustatline; oldcolor = front->vustatcolor; front->vustatline = (STRING)MSG_LOADING; front->vustatcolor = STAT_BUSY; fixcursor(); front->vustatline = (STRING)oldstat; front->vustatcolor = oldcolor; if(!USEPORT(VUSelectPort)) return FALSE; vu->vupaint = (char *)malloc(128 * sizeof(char *)); list = (char **)vu->vupaint; list[0] = 0; pipe(fd); pid = fork(); if(pid < 0) return FALSE; if(pid == 0) { dup2(fd[1], 1); close(fd[1]); close(fd[0]); write(1, "USERLIST\n", 9); execvp(*argv, argv); exit(-1); } close(fd[1]); fp = fdopen(fd[0], "r"); fgets(lbuf, sizeof(lbuf) - 1, fp); while(!feof(fp)) { fgets(lbuf, sizeof(lbuf) - 1, fp); if(feof(fp)) break; p = strchr(lbuf, '\n'); *p = 0; item = (char *)malloc(strlen(lbuf) + 1); strcpy(item, lbuf); VUSelectInsert(vu, VUSelectLocate(vu, item, (int(*)(const char *s1, const char *s2)) VUStricmp), item); } fclose(fp); waitpid(pid, NULL, 0); opts->sel_mark = opts->sel_base = 0; return TRUE; default: break; } return USEPORT(VUSelectPort); }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char *argv[]) { #ifndef OPENPAM struct pam_conv *conv; struct pam_message msg; const struct pam_message *msgp; struct pam_response *resp; #endif struct passwd *pwd; const char *user; const char *crypt_password, *password; int pam_err, retry; (void)argc; (void)argv; /* identify user */ if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS) return (pam_err); if ((pwd = getpwnam(user)) == NULL) return (PAM_USER_UNKNOWN); /* get password */ #ifndef OPENPAM pam_err = pam_get_item(pamh, PAM_CONV, (const void **)&conv); if (pam_err != PAM_SUCCESS) return (PAM_SYSTEM_ERR); msg.msg_style = PAM_PROMPT_ECHO_OFF; msg.msg = password_prompt; msgp = &msg; #endif for (retry = 0; retry < 3; ++retry) { #ifdef OPENPAM pam_err = pam_get_authtok(pamh, PAM_AUTHTOK, &password, NULL); #else resp = NULL; pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr); if (resp != NULL) { if (pam_err == PAM_SUCCESS) password = resp->resp; else free(resp->resp); free(resp); } #endif if (pam_err == PAM_SUCCESS) break; } if (pam_err == PAM_CONV_ERR) return (pam_err); if (pam_err != PAM_SUCCESS) return (PAM_AUTH_ERR); /* compare passwords */ if ((!pwd->pw_passwd[0] && (flags & PAM_DISALLOW_NULL_AUTHTOK)) || (crypt_password = crypt(password, pwd->pw_passwd)) == NULL || strcmp(crypt_password, pwd->pw_passwd) != 0) pam_err = PAM_AUTH_ERR; else pam_err = PAM_SUCCESS; #ifndef OPENPAM free(password); #endif return (pam_err); }
void agentx_parse_agentx_perms(const char *token, char *cptr) { char *socket_perm, *dir_perm, *socket_user, *socket_group; int uid = -1; int gid = -1; int s_perm = -1; int d_perm = -1; char *st; #if HAVE_GETPWNAM && HAVE_PWD_H struct passwd *pwd; #endif #if HAVE_GETGRNAM && HAVE_GRP_H struct group *grp; #endif DEBUGMSGTL(("agentx/config", "port permissions: %s\n", cptr)); socket_perm = strtok_r(cptr, " \t", &st); dir_perm = strtok_r(NULL, " \t", &st); socket_user = strtok_r(NULL, " \t", &st); socket_group = strtok_r(NULL, " \t", &st); if (socket_perm) { s_perm = strtol(socket_perm, NULL, 8); netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCK_PERM, s_perm); DEBUGMSGTL(("agentx/config", "socket permissions: %o (%d)\n", s_perm, s_perm)); } if (dir_perm) { d_perm = strtol(dir_perm, NULL, 8); netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_DIR_PERM, d_perm); DEBUGMSGTL(("agentx/config", "directory permissions: %o (%d)\n", d_perm, d_perm)); } /* * Try to handle numeric UIDs or user names for the socket owner */ if (socket_user) { uid = atoi(socket_user); if ( uid == 0 ) { #if HAVE_GETPWNAM && HAVE_PWD_H pwd = getpwnam( socket_user ); if (pwd) uid = pwd->pw_uid; else #endif snmp_log(LOG_WARNING, "Can't identify AgentX socket user (%s).\n", socket_user); } if ( uid != 0 ) netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCK_USER, uid); DEBUGMSGTL(("agentx/config", "socket owner: %s (%d)\n", socket_user, uid)); } /* * and similarly for the socket group ownership */ if (socket_group) { gid = atoi(socket_group); if ( gid == 0 ) { #if HAVE_GETGRNAM && HAVE_GRP_H grp = getgrnam( socket_group ); if (grp) gid = grp->gr_gid; else #endif snmp_log(LOG_WARNING, "Can't identify AgentX socket group (%s).\n", socket_group); } if ( gid != 0 ) netsnmp_ds_set_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCK_GROUP, gid); DEBUGMSGTL(("agentx/config", "socket group: %s (%d)\n", socket_group, gid)); } }
void init_editfns () { char *user_name; register unsigned char *p, *q; struct passwd *pw; /* password entry for the current user */ Lisp_Object tem; extern char *index (); /* Set up system_name even when dumping. */ Vsystem_name = build_string (get_system_name ()); p = XSTRING (Vsystem_name)->data; while (*p) { if (*p == ' ' || *p == '\t') *p = '-'; p++; } #ifndef CANNOT_DUMP /* Don't bother with this on initial start when just dumping out */ if (!initialized) return; #endif /* not CANNOT_DUMP */ pw = (struct passwd *) getpwuid (getuid ()); Vuser_real_name = build_string (pw ? pw->pw_name : "unknown"); user_name = (char *) getenv ("USER"); if (!user_name) user_name = (char *) getenv ("LOGNAME"); /* USG equivalent */ if (user_name) Vuser_name = build_string (user_name); else Vuser_name = Vuser_real_name; tem = Fstring_equal (Vuser_name, Vuser_real_name); if (!NULL (tem)) pw = (struct passwd *) getpwnam (user_name); p = (unsigned char *) (pw ? USER_FULL_NAME : "unknown"); q = (unsigned char *) index (p, ','); Vuser_full_name = make_string (p, q ? q - p : strlen (p)); #ifdef AMPERSAND_FULL_NAME p = XSTRING (Vuser_full_name)->data; q = (unsigned char *) index (p, '&'); /* Substitute the login name for the &, upcasing the first character. */ if (q) { char *r = (char *) alloca (strlen (p) + XSTRING (Vuser_name)->size + 1); bcopy (p, r, q - p); r[q - p] = 0; strcat (r, XSTRING (Vuser_real_name)->data); r[q - p] = UPCASE (r[q - p]); strcat (r, q + 1); Vuser_full_name = build_string (r); } #endif /* AMPERSAND_FULL_NAME */ }
Server::Server() : m_lockFileName(Config::Instance()->lockFileName), m_pidFileName(Config::Instance()->pidFileName) { pid_t pid, sid, parent; int lfp = -1; struct stat sb; /* already a daemon */ if(getppid() == 1) return; if(m_lockFileName.size()) { if (stat(m_lockFileName.c_str(), &sb) != -1) { syslog(LOG_INFO, "another process running?"); if( getProcIdByName(__progname) > 0) { syslog(LOG_ERR, "exit"); exit(EXIT_FAILURE); } else { ::remove(m_lockFileName.c_str()); } } lfp = open(m_lockFileName.c_str(),O_RDWR|O_CREAT,0640); if(lfp < 0) { syslog(LOG_ERR, "unable to create lock file %s, code=%d (%s). exit", m_lockFileName.c_str(), errno, strerror(errno)); exit(EXIT_FAILURE); } } if(getuid() == 0 || geteuid() == 0) { struct passwd *pw = getpwnam(Config::Instance()->asUser.c_str()); if(pw) { syslog(LOG_NOTICE, "setting user to %s",Config::Instance()->asUser.c_str()); if(setuid(pw->pw_uid)) syslog(LOG_ERR,"error set uid"); } } signal(SIGCHLD,child_handler); signal(SIGUSR1,child_handler); signal(SIGALRM,child_handler); pid = fork(); if(pid < 0) { syslog(LOG_ERR, "unable to fork daemon, code=%d (%s). exit", errno, strerror(errno)); exit(EXIT_FAILURE); } if(pid > 0) { alarm(2); pause(); exit(EXIT_FAILURE); } parent = getppid(); signal(SIGCHLD,SIG_DFL); signal(SIGTSTP,SIG_IGN); signal(SIGTTOU,SIG_IGN); signal(SIGTTIN,SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTERM,SIG_DFL); signal(SIGPIPE,SIG_IGN); signal(SIGRTMIN,SIG_DFL); umask(007); sid = setsid(); if(sid < 0) { syslog(LOG_ERR, "unable to create a new session, code %d (%s)", errno, strerror(errno)); // exit(EXIT_FAILURE); } if((chdir("/")) < 0) { syslog(LOG_ERR, "unable to change directory to %s, code %d (%s). exit", "/", errno, strerror(errno)); // exit(EXIT_FAILURE); } if(!freopen("/dev/null", "r", stdin)) syslog(LOG_ERR, "unable to change stdin"); if(Config::Instance()->debug) { if(freopen(Config::Instance()->debug_file.c_str(), "w", stdout)) syslog(LOG_ERR, "unable to change stdout to:%s",Config::Instance()->debug_file.c_str()); if(!freopen(Config::Instance()->debug_file.c_str(), "w", stderr)) syslog(LOG_ERR, "unable to change stdin %s",Config::Instance()->debug_file.c_str()); printf("start\n"); } else { if(freopen("/dev/null", "w", stdout)) syslog(LOG_ERR, "unable to change stdout"); if(!freopen("/dev/null", "w", stderr)) syslog(LOG_ERR, "unable to change stderr"); kill(parent, SIGUSR1); } struct sched_param param; param.sched_priority = 49; if(sched_setscheduler(0, SCHED_FIFO, ¶m) == -1) { syslog(LOG_ERR,"sched_setscheduler failed"); //exit(-1); } if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) { syslog(LOG_ERR,"mlockall failed"); //exit(-2); } writePid(m_pidFileName); syslog(LOG_NOTICE, "staring: done"); }
int main(int argc, char ** argv) { int c; int flags = MS_MANDLOCK; /* no need to set legacy MS_MGC_VAL */ char * orgoptions = NULL; char * share_name = NULL; char * ipaddr = NULL; char * uuid = NULL; char * mountpoint = NULL; char * options = NULL; char * resolved_path = NULL; char * temp; int rc; int rsize = 0; int wsize = 0; int nomtab = 0; int uid = 0; int gid = 0; int optlen = 0; int orgoptlen = 0; size_t options_size = 0; int retry = 0; /* set when we have to retry mount with uppercase */ struct stat statbuf; struct utsname sysinfo; struct mntent mountent; FILE * pmntfile; /* setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); */ if(argc && argv) { thisprogram = argv[0]; } else { mount_cifs_usage(); exit(1); } if(thisprogram == NULL) thisprogram = "mount.cifs"; uname(&sysinfo); /* BB add workstation name and domain and pass down */ /* #ifdef _GNU_SOURCE printf(" node: %s machine: %s sysname %s domain %s\n", sysinfo.nodename,sysinfo.machine,sysinfo.sysname,sysinfo.domainname); #endif */ if(argc > 2) { share_name = argv[1]; mountpoint = argv[2]; } /* add sharename in opts string as unc= parm */ while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsSU:vVwt:", longopts, NULL)) != -1) { switch (c) { /* No code to do the following options yet */ /* case 'l': list_with_volumelabel = 1; break; case 'L': volumelabel = optarg; break; */ /* case 'a': ++mount_all; break; */ case '?': case 'h': /* help */ mount_cifs_usage (); exit(1); case 'n': ++nomtab; break; case 'b': #ifdef MS_BIND flags |= MS_BIND; #else fprintf(stderr, "option 'b' (MS_BIND) not supported\n"); #endif break; case 'm': #ifdef MS_MOVE flags |= MS_MOVE; #else fprintf(stderr, "option 'm' (MS_MOVE) not supported\n"); #endif break; case 'o': orgoptions = strdup(optarg); break; case 'r': /* mount readonly */ flags |= MS_RDONLY; break; case 'U': uuid = optarg; break; case 'v': ++verboseflag; break; case 'V': printf ("mount.cifs version: %s.%s%s\n", MOUNT_CIFS_VERSION_MAJOR, MOUNT_CIFS_VERSION_MINOR, MOUNT_CIFS_VENDOR_SUFFIX); if(mountpassword) { memset(mountpassword,0,64); } exit (0); case 'w': flags &= ~MS_RDONLY; break; case 'R': rsize = atoi(optarg) ; break; case 'W': wsize = atoi(optarg); break; case '1': if (isdigit(*optarg)) { char *ep; uid = strtoul(optarg, &ep, 10); if (*ep) { printf("bad uid value \"%s\"\n", optarg); exit(1); } } else { struct passwd *pw; if (!(pw = getpwnam(optarg))) { printf("bad user name \"%s\"\n", optarg); exit(1); } uid = pw->pw_uid; endpwent(); } break; case '2': if (isdigit(*optarg)) { char *ep; gid = strtoul(optarg, &ep, 10); if (*ep) { printf("bad gid value \"%s\"\n", optarg); exit(1); } } else { struct group *gr; if (!(gr = getgrnam(optarg))) { printf("bad user name \"%s\"\n", optarg); exit(1); } gid = gr->gr_gid; endpwent(); } break; case 'u': got_user = 1; user_name = optarg; break; case 'd': domain_name = optarg; /* BB fix this - currently ignored */ got_domain = 1; break; case 'p': if(mountpassword == NULL) mountpassword = (char *)calloc(65,1); if(mountpassword) { got_password = 1; strncpy(mountpassword,optarg,64); } break; case 'S': get_password_from_file(0 /* stdin */,NULL); break; case 't': break; default: printf("unknown mount option %c\n",c); mount_cifs_usage(); exit(1); } } if((argc < 3) || (share_name == NULL) || (mountpoint == NULL)) { mount_cifs_usage(); exit(1); } if (getenv("PASSWD")) { if(mountpassword == NULL) mountpassword = (char *)calloc(65,1); if(mountpassword) { strncpy(mountpassword,getenv("PASSWD"),64); got_password = 1; } } else if (getenv("PASSWD_FD")) { get_password_from_file(atoi(getenv("PASSWD_FD")),NULL); } else if (getenv("PASSWD_FILE")) { get_password_from_file(0, getenv("PASSWD_FILE")); } if (orgoptions && parse_options(&orgoptions, &flags)) { rc = -1; goto mount_exit; } ipaddr = parse_server(&share_name); if((ipaddr == NULL) && (got_ip == 0)) { printf("No ip address specified and hostname not found\n"); rc = -1; goto mount_exit; } /* BB save off path and pop after mount returns? */ resolved_path = (char *)malloc(PATH_MAX+1); if(resolved_path) { /* Note that if we can not canonicalize the name, we get another chance to see if it is valid when we chdir to it */ if (realpath(mountpoint, resolved_path)) { mountpoint = resolved_path; } } if(chdir(mountpoint)) { printf("mount error: can not change directory into mount target %s\n",mountpoint); rc = -1; goto mount_exit; } if(stat (".", &statbuf)) { printf("mount error: mount point %s does not exist\n",mountpoint); rc = -1; goto mount_exit; } if (S_ISDIR(statbuf.st_mode) == 0) { printf("mount error: mount point %s is not a directory\n",mountpoint); rc = -1; goto mount_exit; } if((getuid() != 0) && (geteuid() == 0)) { if((statbuf.st_uid == getuid()) && (S_IRWXU == (statbuf.st_mode & S_IRWXU))) { #ifndef CIFS_ALLOW_USR_SUID /* Do not allow user mounts to control suid flag for mount unless explicitly built that way */ flags |= MS_NOSUID | MS_NODEV; #endif } else { printf("mount error: permission denied or not superuser and mount.cifs not installed SUID\n"); return -1; } } if(got_user == 0) { user_name = getusername(); got_user = 1; } if(got_password == 0) { char *tmp_pass; tmp_pass = getpass("Password: "******"Password not entered, exiting.\n"); return -1; } strncpy(mountpassword, tmp_pass, 64); got_password = 1; } /* FIXME launch daemon (handles dfs name resolution and credential change) remember to clear parms and overwrite password field before launching */ mount_retry: if(orgoptions) { optlen = strlen(orgoptions); orgoptlen = optlen; } else optlen = 0; if(share_name) optlen += strlen(share_name) + 4; else { printf("No server share name specified\n"); printf("\nMounting the DFS root for server not implemented yet\n"); exit(1); } if(user_name) optlen += strlen(user_name) + 6; if(ipaddr) optlen += strlen(ipaddr) + 4; if(mountpassword) optlen += strlen(mountpassword) + 6; if(options) { free(options); options = NULL; } options_size = optlen + 10 + 64; options = (char *)malloc(options_size /* space for commas in password */ + 8 /* space for domain= , domain name itself was counted as part of the length username string above */); if(options == NULL) { printf("Could not allocate memory for mount options\n"); return -1; } options[0] = 0; strlcpy(options,"unc=",options_size); strlcat(options,share_name,options_size); /* scan backwards and reverse direction of slash */ temp = strrchr(options, '/'); if(temp > options + 6) *temp = '\\'; if(ipaddr) { strlcat(options,",ip=",options_size); strlcat(options,ipaddr,options_size); } if(user_name) { /* check for syntax like user=domain\user */ if(got_domain == 0) domain_name = check_for_domain(&user_name); strlcat(options,",user="******",domain=",options_size); strlcat(options,domain_name,options_size); } } if(mountpassword) { /* Commas have to be doubled, or else they will look like the parameter separator */ /* if(sep is not set)*/ if(retry == 0) check_for_comma(&mountpassword); strlcat(options,",pass="******",ver=",options_size); strlcat(options,MOUNT_CIFS_VERSION_MAJOR,options_size); if(orgoptions) { strlcat(options,",",options_size); strlcat(options,orgoptions,options_size); } if(prefixpath) { strlcat(options,",prefixpath=",options_size); strlcat(options,prefixpath,options_size); /* no need to cat the / */ } if(verboseflag) printf("\nmount.cifs kernel mount options %s \n",options); if(mount(share_name, mountpoint, "cifs", flags, options)) { /* remember to kill daemon on error */ char * tmp; switch (errno) { case 0: printf("mount failed but no error number set\n"); break; case ENODEV: printf("mount error: cifs filesystem not supported by the system\n"); break; case ENXIO: if(retry == 0) { retry = 1; tmp = share_name; while (*tmp && !(((unsigned char)tmp[0]) & 0x80)) { *tmp = toupper((unsigned char)*tmp); tmp++; } if(!*tmp) { printf("retrying with upper case share name\n"); goto mount_retry; } } default: printf("mount error %d = %s\n",errno,strerror(errno)); } printf("Refer to the mount.cifs(8) manual page (e.g.man mount.cifs)\n"); rc = -1; goto mount_exit; } else { pmntfile = setmntent(MOUNTED, "a+"); if(pmntfile) { mountent.mnt_fsname = share_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = CONST_DISCARD(char *,"cifs"); mountent.mnt_opts = (char *)malloc(220); if(mountent.mnt_opts) { char * mount_user = getusername(); memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) strlcat(mountent.mnt_opts,"ro",220); else strlcat(mountent.mnt_opts,"rw",220); if(flags & MS_MANDLOCK) strlcat(mountent.mnt_opts,",mand",220); if(flags & MS_NOEXEC) strlcat(mountent.mnt_opts,",noexec",220); if(flags & MS_NOSUID) strlcat(mountent.mnt_opts,",nosuid",220); if(flags & MS_NODEV) strlcat(mountent.mnt_opts,",nodev",220); if(flags & MS_SYNCHRONOUS) strlcat(mountent.mnt_opts,",synch",220); if(mount_user) { if(getuid() != 0) { strlcat(mountent.mnt_opts,",user="******"could not update mount table\n"); } }