int lxdm_auth_user_authenticate(LXDM_AUTH *a,const char *user,const char *pass,int type) { struct passwd *pw; struct spwd *sp; char *real; char *enc; if(!user || !user[0]) { g_debug("user==NULL\n"); return AUTH_ERROR; } pw = getpwnam(user); endpwent(); if(!pw) { g_debug("user %s not found\n",user); return AUTH_BAD_USER; } if(strstr(pw->pw_shell, "nologin")) { g_debug("user %s have nologin shell\n",user); return AUTH_PRIV; } if(type==AUTH_TYPE_AUTO_LOGIN && !pass) { goto out; } sp = getspnam(user); if( !sp ) { return AUTH_FAIL; } endspent(); real = sp->sp_pwdp; if( !real || !real[0] ) { if( !pass || !pass[0] ) { passwd_copy(&a->pw,pw); g_debug("user %s auth with no password ok\n",user); return AUTH_SUCCESS; } else { g_debug("user %s password not match\n",user); return AUTH_FAIL; } } enc = crypt(pass, real); if( strcmp(real, enc) ) { g_debug("user %s password not match\n",user); return AUTH_FAIL; } out: g_debug("user %s auth ok\n",pw->pw_name); passwd_copy(&a->pw,pw); return AUTH_SUCCESS; }
int lxdm_auth_user_authenticate(LXDM_AUTH *a,const char *user,const char *pass,int type) { struct passwd *pw; if(!user || !user[0]) { g_debug("user==NULL\n"); return AUTH_ERROR; } pw = getpwnam(user); endpwent(); if(!pw) { g_debug("user %s not found\n",user); return AUTH_BAD_USER; } if(strstr(pw->pw_shell, "nologin")) { g_debug("user %s have nologin shell\n",user); return AUTH_PRIV; } if(a->handle) pam_end(a->handle,0); if(PAM_SUCCESS != pam_start("lxdm", pw->pw_name, &conv, (pam_handle_t**)&a->handle)) { a->handle=NULL; g_debug("user %s start pam fail\n",user); return AUTH_FAIL; } else { int ret; if(type==AUTH_TYPE_AUTO_LOGIN && !pass) goto out; user_pass[0]=(char*)user;user_pass[1]=(char*)pass; ret=pam_authenticate(a->handle,PAM_SILENT); user_pass[0]=0;user_pass[1]=0; if(ret!=PAM_SUCCESS) { g_debug("user %s auth fail with %d\n",user,ret); return AUTH_FAIL; } ret=pam_acct_mgmt(a->handle,PAM_SILENT); if(ret!=PAM_SUCCESS) { g_debug("user %s acct mgmt fail with %d\n",user,ret); return AUTH_FAIL; } } out: passwd_copy(&a->pw,pw); return AUTH_SUCCESS; }
int main(int argc, char **argv) { enum { NNP = CHAR_MAX + 1, RUID, EUID, RGID, EGID, REUID, REGID, CLEAR_GROUPS, KEEP_GROUPS, INIT_GROUPS, GROUPS, INHCAPS, AMBCAPS, LISTCAPS, CAPBSET, SECUREBITS, PDEATHSIG, SELINUX_LABEL, APPARMOR_PROFILE }; static const struct option longopts[] = { { "dump", no_argument, NULL, 'd' }, { "nnp", no_argument, NULL, NNP }, { "no-new-privs", no_argument, NULL, NNP }, { "inh-caps", required_argument, NULL, INHCAPS }, { "ambient-caps", required_argument, NULL, AMBCAPS }, { "list-caps", no_argument, NULL, LISTCAPS }, { "ruid", required_argument, NULL, RUID }, { "euid", required_argument, NULL, EUID }, { "rgid", required_argument, NULL, RGID }, { "egid", required_argument, NULL, EGID }, { "reuid", required_argument, NULL, REUID }, { "regid", required_argument, NULL, REGID }, { "clear-groups", no_argument, NULL, CLEAR_GROUPS }, { "keep-groups", no_argument, NULL, KEEP_GROUPS }, { "init-groups", no_argument, NULL, INIT_GROUPS }, { "groups", required_argument, NULL, GROUPS }, { "bounding-set", required_argument, NULL, CAPBSET }, { "securebits", required_argument, NULL, SECUREBITS }, { "pdeathsig", required_argument, NULL, PDEATHSIG, }, { "selinux-label", required_argument, NULL, SELINUX_LABEL }, { "apparmor-profile", required_argument, NULL, APPARMOR_PROFILE }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; static const ul_excl_t excl[] = { /* keep in same order with enum definitions */ {CLEAR_GROUPS, KEEP_GROUPS, INIT_GROUPS, GROUPS}, {0} }; int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT; int c; struct privctx opts; struct passwd *pw = NULL; int dumplevel = 0; int total_opts = 0; int list_caps = 0; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); atexit(close_stdout); memset(&opts, 0, sizeof(opts)); while ((c = getopt_long(argc, argv, "+dhV", longopts, NULL)) != -1) { err_exclusive_options(c, longopts, excl, excl_st); total_opts++; switch (c) { case 'd': dumplevel++; break; case NNP: if (opts.nnp) errx(EXIT_FAILURE, _("duplicate --no-new-privs option")); opts.nnp = 1; break; case RUID: if (opts.have_ruid) errx(EXIT_FAILURE, _("duplicate ruid")); opts.have_ruid = 1; pw = get_passwd(optarg, &opts.ruid, _("failed to parse ruid")); if (pw) { passwd_copy(&opts.passwd, pw); opts.have_passwd = 1; } break; case EUID: if (opts.have_euid) errx(EXIT_FAILURE, _("duplicate euid")); opts.have_euid = 1; opts.euid = get_user(optarg, _("failed to parse euid")); break; case REUID: if (opts.have_ruid || opts.have_euid) errx(EXIT_FAILURE, _("duplicate ruid or euid")); opts.have_ruid = opts.have_euid = 1; pw = get_passwd(optarg, &opts.ruid, _("failed to parse reuid")); opts.euid = opts.ruid; if (pw) { passwd_copy(&opts.passwd, pw); opts.have_passwd = 1; } break; case RGID: if (opts.have_rgid) errx(EXIT_FAILURE, _("duplicate rgid")); opts.have_rgid = 1; opts.rgid = get_group(optarg, _("failed to parse rgid")); break; case EGID: if (opts.have_egid) errx(EXIT_FAILURE, _("duplicate egid")); opts.have_egid = 1; opts.egid = get_group(optarg, _("failed to parse egid")); break; case REGID: if (opts.have_rgid || opts.have_egid) errx(EXIT_FAILURE, _("duplicate rgid or egid")); opts.have_rgid = opts.have_egid = 1; opts.rgid = opts.egid = get_group(optarg, _("failed to parse regid")); break; case CLEAR_GROUPS: if (opts.clear_groups) errx(EXIT_FAILURE, _("duplicate --clear-groups option")); opts.clear_groups = 1; break; case KEEP_GROUPS: if (opts.keep_groups) errx(EXIT_FAILURE, _("duplicate --keep-groups option")); opts.keep_groups = 1; break; case INIT_GROUPS: if (opts.init_groups) errx(EXIT_FAILURE, _("duplicate --init-groups option")); opts.init_groups = 1; break; case GROUPS: if (opts.have_groups) errx(EXIT_FAILURE, _("duplicate --groups option")); parse_groups(&opts, optarg); break; case PDEATHSIG: if (opts.pdeathsig) errx(EXIT_FAILURE, _("duplicate --keep-pdeathsig option")); parse_pdeathsig(&opts, optarg); break; case LISTCAPS: list_caps = 1; break; case INHCAPS: if (opts.caps_to_inherit) errx(EXIT_FAILURE, _("duplicate --inh-caps option")); opts.caps_to_inherit = optarg; break; case AMBCAPS: if (opts.ambient_caps) errx(EXIT_FAILURE, _("duplicate --ambient-caps option")); opts.ambient_caps = optarg; break; case CAPBSET: if (opts.bounding_set) errx(EXIT_FAILURE, _("duplicate --bounding-set option")); opts.bounding_set = optarg; break; case SECUREBITS: if (opts.have_securebits) errx(EXIT_FAILURE, _("duplicate --securebits option")); parse_securebits(&opts, optarg); break; case SELINUX_LABEL: if (opts.selinux_label) errx(EXIT_FAILURE, _("duplicate --selinux-label option")); opts.selinux_label = optarg; break; case APPARMOR_PROFILE: if (opts.apparmor_profile) errx(EXIT_FAILURE, _("duplicate --apparmor-profile option")); opts.apparmor_profile = optarg; break; case 'h': usage(); case 'V': printf(UTIL_LINUX_VERSION); return EXIT_SUCCESS; default: errtryhelp(EXIT_FAILURE); } } if (dumplevel) { if (total_opts != dumplevel || optind < argc) errx(EXIT_FAILURE, _("--dump is incompatible with all other options")); dump(dumplevel); return EXIT_SUCCESS; } if (list_caps) { if (total_opts != 1 || optind < argc) errx(EXIT_FAILURE, _("--list-caps must be specified alone")); list_known_caps(); return EXIT_SUCCESS; } if (argc <= optind) errx(EXIT_FAILURE, _("No program specified")); if ((opts.have_rgid || opts.have_egid) && !opts.keep_groups && !opts.clear_groups && !opts.init_groups && !opts.have_groups) errx(EXIT_FAILURE, _("--[re]gid requires --keep-groups, --clear-groups, --init-groups, or --groups")); if (opts.init_groups && !opts.have_ruid) errx(EXIT_FAILURE, _("--init-groups requires --ruid or --reuid")); if (opts.init_groups && !opts.have_passwd) errx(EXIT_FAILURE, _("uid %ld not found, --init-groups requires an user that " "can be found on the system"), (long) opts.ruid); if (opts.nnp && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) err(EXIT_FAILURE, _("disallow granting new privileges failed")); if (opts.selinux_label) do_selinux_label(opts.selinux_label); if (opts.apparmor_profile) do_apparmor_profile(opts.apparmor_profile); if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) err(EXIT_FAILURE, _("keep process capabilities failed")); /* We're going to want CAP_SETPCAP, CAP_SETUID, and CAP_SETGID if * possible. */ bump_cap(CAP_SETPCAP); bump_cap(CAP_SETUID); bump_cap(CAP_SETGID); if (capng_apply(CAPNG_SELECT_CAPS) != 0) err(SETPRIV_EXIT_PRIVERR, _("activate capabilities")); if (opts.have_ruid || opts.have_euid) { do_setresuid(&opts); /* KEEPCAPS doesn't work for the effective mask. */ if (capng_apply(CAPNG_SELECT_CAPS) != 0) err(SETPRIV_EXIT_PRIVERR, _("reactivate capabilities")); } if (opts.have_rgid || opts.have_egid) do_setresgid(&opts); if (opts.have_groups) { if (setgroups(opts.num_groups, opts.groups) != 0) err(SETPRIV_EXIT_PRIVERR, _("setgroups failed")); } else if (opts.init_groups) { if (initgroups(opts.passwd.pw_name, opts.passwd.pw_gid) != 0) err(SETPRIV_EXIT_PRIVERR, _("initgroups failed")); } else if (opts.clear_groups) { gid_t x = 0; if (setgroups(0, &x) != 0) err(SETPRIV_EXIT_PRIVERR, _("setgroups failed")); } if (opts.have_securebits && prctl(PR_SET_SECUREBITS, opts.securebits, 0, 0, 0) != 0) err(SETPRIV_EXIT_PRIVERR, _("set process securebits failed")); if (opts.bounding_set) { do_caps(CAP_TYPE_BOUNDING, opts.bounding_set); errno = EPERM; /* capng doesn't set errno if we're missing CAP_SETPCAP */ if (capng_apply(CAPNG_SELECT_BOUNDS) != 0) err(SETPRIV_EXIT_PRIVERR, _("apply bounding set")); } if (opts.caps_to_inherit) { do_caps(CAP_TYPE_INHERITABLE, opts.caps_to_inherit); if (capng_apply(CAPNG_SELECT_CAPS) != 0) err(SETPRIV_EXIT_PRIVERR, _("apply capabilities")); } if (opts.ambient_caps) { do_caps(CAP_TYPE_AMBIENT, opts.ambient_caps); } /* Clear or set parent death signal */ if (opts.pdeathsig && prctl(PR_SET_PDEATHSIG, opts.pdeathsig < 0 ? 0 : opts.pdeathsig) != 0) err(SETPRIV_EXIT_PRIVERR, _("set parent death signal failed")); execvp(argv[optind], argv + optind); errexec(argv[optind]); }