static int _set_options(const int argc, char **argv) { int option_index = 0; int cc; char *next_str = NULL; static struct option long_options[] = { {"configdir", required_argument, 0, 'c'}, {"measure", no_argument, 0, 'm'}, {"testcases", required_argument, 0, 't'}, {"usage", no_argument, 0, 'U'}, {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}}; _init_opts(); while ((cc = getopt_long(argc, argv, "cmt:Uv", long_options, &option_index)) != EOF) { switch (cc) { case 'c': params.configdir = xstrdup(optarg); break; case 'm': params.measure++; break; case 't': params.testcases = xstrdup(optarg); break; case 'U': _help_msg(); return -1; break; case 'v': params.verbose++; break; case ':': case '?': /* getopt() has explained it */ return -1; } } return 0; }
static void _set_options(const int argc, char **argv) { int option_index = 0, c; log_options_t logopt = LOG_OPTS_STDERR_ONLY; char *next_str = NULL; uid_t uid = -1; static struct option long_options[] = { {"extract", no_argument, 0, 'E'}, {"help", no_argument, 0, 'h'}, {"job", required_argument, 0, 'j'}, {"input", required_argument, 0, 'i'}, {"level", required_argument, 0, 'l'}, {"node", required_argument, 0, 'N'}, {"output", required_argument, 0, 'o'}, {"profiledir", required_argument, 0, 'p'}, {"series", required_argument, 0, 's'}, {"savefiles", no_argument, 0, 'S'}, {"usage", 0, ¶ms.help, 3}, {"user", required_argument, 0, 'u'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, {0, 0, 0, 0}}; log_init(xbasename(argv[0]), logopt, 0, NULL); _init_opts(); while (1) { /* now cycle through the command line */ c = getopt_long(argc, argv, "Ehi:j:l:N:o:p:s:Su:vV", long_options, &option_index); if (c == -1) break; switch (c) { case 'E': params.mode = SH5UTIL_MODE_EXTRACT; break; case 'h': params.help = 1; break; case 'i': params.input = xstrdup(optarg); break; case 'j': params.job_id = strtol(optarg, &next_str, 10); if (next_str[0] == '.') params.step_id = strtol(next_str+1, NULL, 10); break; case 'l': params.level = xstrdup(optarg); break; case 'N': params.node = xstrdup(optarg); break; case 'o': params.output = xstrdup(optarg); break; case 'p': params.dir = xstrdup(optarg); break; case 's': params.series = xstrdup(optarg); break; case 'S': params.keepfiles = 1; break; case 'u': if (uid_from_string (optarg, &uid) < 0) { error("--uid=\"%s\" invalid", optarg); exit(1); } break; case (int)'v': params.verbose++; break; case (int)'V': print_slurm_version(); exit(0); break; case ':': case '?': /* getopt() has explained it */ exit(1); } } if (params.help) { switch (params.help) { case 1: case 3: _help_msg(); break; default: fprintf(stderr, "bug: --help=%d\n", params.help); } exit(0); } if (params.job_id == -1) fatal("You need to supply a --jobs value."); if (uid == -1) uid = getuid(); params.user = uid_to_string(uid); if (!params.dir) acct_gather_profile_g_get(ACCT_GATHER_PROFILE_DIR, ¶ms.dir); if (!params.dir) fatal("You need to supply a --profiledir or be on a " "node with a valid acct_gather.conf"); if (params.verbose) { logopt.stderr_level += params.verbose; log_alter(logopt, SYSLOG_FACILITY_USER, NULL); } /* FIXME : For now all these only work for extract. Seems * like it would be easy to add the logic to "merge" as well. */ if (params.input || params.level || params.node || (params.step_id != -1) || params.series) params.mode = SH5UTIL_MODE_EXTRACT; if (params.mode == SH5UTIL_MODE_EXTRACT) { if (!params.level) params.level = xstrdup("Node:Totals"); if (!params.input) params.input = xstrdup_printf( "./job_%d.h5", params.job_id); if (!params.output) params.output = xstrdup_printf( "./extract_%d.csv", params.job_id); } if (!params.output) params.output = xstrdup_printf("./job_%d.h5", params.job_id); }
/* Parse arguments, etc then get my socket address/port information. Attempt to * adopt this process into a job in the following order: * 1) If the user has only one job on the node, pick that one * 2) Send RPC to source IP of socket. If there is a slurmd at the IP * address, ask it which job I belong to. On success, pick that one * 3) Pick a job semi-randomly (default) or skip the adoption (if * configured) */ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags __attribute__((unused)), int argc, const char **argv) { int retval = PAM_IGNORE, rc, slurmrc, bufsize, user_jobs; char *user_name; List steps = NULL; step_loc_t *stepd = NULL; struct passwd pwd, *pwd_result; char *buf = NULL; _init_opts(); _parse_opts(pamh, argc, argv); _log_init(opts.log_level); switch (opts.action_generic_failure) { case CALLERID_ACTION_DENY: rc = PAM_PERM_DENIED; break; case CALLERID_ACTION_ALLOW: rc = PAM_SUCCESS; break; case CALLERID_ACTION_IGNORE: rc = PAM_IGNORE; break; /* Newer gcc versions warn if enum cases are missing */ default: error("The code is broken!!!!"); } retval = pam_get_item(pamh, PAM_USER, (void *) &user_name); if (user_name == NULL || retval != PAM_SUCCESS) { pam_syslog(pamh, LOG_ERR, "No username in PAM_USER? Fail!"); return PAM_SESSION_ERR; } /* Check for an unsafe config that might lock out root. This is a very * basic check that shouldn't be 100% relied on */ if (!opts.ignore_root && (opts.action_unknown == CALLERID_ACTION_DENY || opts.action_no_jobs != CALLERID_ACTION_ALLOW || opts.action_adopt_failure != CALLERID_ACTION_ALLOW || opts.action_generic_failure != CALLERID_ACTION_ALLOW )) { /* Let's get verbose */ info("==============================="); info("Danger!!!"); info("A crazy admin set ignore_root=0 and some unsafe actions"); info("You might lock out root!"); info("If this is desirable, modify the source code"); info("Setting ignore_root=1 and continuing"); opts.ignore_root = 1; } /* Ignoring root is probably best but the admin can allow it */ if (!strcmp(user_name, "root")) { if (opts.ignore_root) { info("Ignoring root user"); return PAM_IGNORE; } else { /* This administrator is crazy */ info("Danger!!! This is a connection attempt by root and ignore_root=0 is set! Hope for the best!"); } } /* Calculate buffer size for getpwnam_r */ bufsize = sysconf(_SC_GETPW_R_SIZE_MAX); if (bufsize == -1) bufsize = 16384; /* take a large guess */ buf = xmalloc(bufsize); retval = getpwnam_r(user_name, &pwd, buf, bufsize, &pwd_result); if (pwd_result == NULL) { if (retval == 0) { error("getpwnam_r could not locate %s", user_name); } else { errno = retval; error("getpwnam_r: %m"); } xfree(buf); return PAM_SESSION_ERR; } if (_load_cgroup_config() != SLURM_SUCCESS) return rc; /* Check if there are any steps on the node from any user. A failure here * likely means failures everywhere so exit on failure or if no local jobs * exist. */ steps = stepd_available(NULL, opts.node_name); if (!steps) { error("Error obtaining local step information."); goto cleanup; } /* Check to see if this user has only one job on the node. If so, choose * that job and adopt this process into it (unless configured not to) */ user_jobs = _user_job_count(steps, pwd.pw_uid, &stepd); if (user_jobs == 0) { if (opts.action_no_jobs == CALLERID_ACTION_DENY) { send_user_msg(pamh, "Access denied by " PAM_MODULE_NAME ": you have no active jobs on this node"); rc = PAM_PERM_DENIED; } else { debug("uid %u owns no jobs but action_no_jobs=ignore", pwd.pw_uid); rc = PAM_IGNORE; } goto cleanup; } else if (user_jobs == 1) { if (opts.single_job_skip_rpc) { info("Connection by user %s: user has only one job %u", user_name, stepd->jobid); slurmrc = _adopt_process(getpid(), stepd); /* If adoption into the only job fails, it is time to * exit. Return code is based on the * action_adopt_failure setting */ if (slurmrc == SLURM_SUCCESS || (opts.action_adopt_failure == CALLERID_ACTION_ALLOW)) rc = PAM_SUCCESS; else rc = PAM_PERM_DENIED; goto cleanup; } } else { debug("uid %u has %d jobs", pwd.pw_uid, user_jobs); } /* Single job check turned up nothing (or we skipped it). Make RPC call * to slurmd at source IP. If it can tell us the job, the function calls * _adopt_process */ rc = _try_rpc(&pwd); if (rc == PAM_SUCCESS) goto cleanup; /* The source of the connection either didn't reply or couldn't * determine the job ID at the source. Proceed to action_unknown */ rc = _action_unknown(pamh, &pwd, steps); cleanup: FREE_NULL_LIST(steps); xfree(buf); xfree(slurm_cgroup_conf); xfree(opts.node_name); return rc; }