int login_desrpc(const char *passwd) { char netname[MAXNETNAMELEN + 1]; char secretkey[HEXKEYBYTES + 1]; if (getnetname(netname) == 0) return -1; if (getsecretkey(netname, secretkey, passwd) == 0) return -1; if (secretkey[0] == 0) { fprintf(stderr, _("Password does not decrypt secret key for %s.\n"), netname); return -1; } if (key_setsecret(secretkey) < 0) { fprintf(stderr, _("Could not set %s's secret key: is the keyserv daemon running?\n"), netname); return -1; } return 0; }
int main(void) { char fullname[MAXNETNAMELEN + 1]; struct key_netstarg netst; if (!getnetname(fullname)) { fprintf(stderr, "netname lookup failed -- make sure the "); fprintf(stderr, "system domain name is set.\n"); exit(1); } if (! getsecretkey(fullname, (char *)&(netst.st_priv_key), getpass("Password:"******"Can't find %s's secret key\n", fullname); exit(1); } if (netst.st_priv_key[0] == 0) { fprintf(stderr, "Password incorrect for %s\n", fullname); exit(1); } netst.st_pub_key[0] = 0; netst.st_netname = strdup(fullname); if (key_setnet(&netst) < 0) { fprintf(stderr, "Could not set %s's secret key\n", fullname); fprintf(stderr, "Maybe the keyserver is down?\n"); exit(1); } exit(0); /* NOTREACHED */ }
static Bool StartClient ( struct verify_info *verify, struct display *d, int *pidp, char *name, char *passwd) { char **f, *home; char *failsafeArgv[2]; int pid; #ifdef HAS_SETUSERCONTEXT struct passwd* pwd; #endif #ifdef USE_PAM pam_handle_t *pamh = thepamh(); #endif if (verify->argv) { Debug ("StartSession %s: ", verify->argv[0]); for (f = verify->argv; *f; f++) Debug ("%s ", *f); Debug ("; "); } if (verify->userEnviron) { for (f = verify->userEnviron; *f; f++) Debug ("%s ", *f); Debug ("\n"); } #ifdef USE_PAM if (pamh) pam_open_session(pamh, 0); #endif switch (pid = fork ()) { case 0: CleanUpChild (); #ifdef XDMCP /* The chooser socket is not closed by CleanUpChild() */ DestroyWellKnownSockets(); #endif /* Do system-dependent login setup here */ #ifdef USE_PAM /* pass in environment variables set by libpam and modules it called */ if (pamh) { long i; char **pam_env = pam_getenvlist(pamh); for(i = 0; pam_env && pam_env[i]; i++) { verify->userEnviron = putEnv(pam_env[i], verify->userEnviron); } } #endif #ifndef AIXV3 #ifndef HAS_SETUSERCONTEXT if (setgid(verify->gid) < 0) { LogError("setgid %d (user \"%s\") failed, errno=%d\n", verify->gid, name, errno); return (0); } #if defined(BSD) && (BSD >= 199103) if (setlogin(name) < 0) { LogError("setlogin for \"%s\" failed, errno=%d", name, errno); return(0); } #endif #ifndef QNX4 if (initgroups(name, verify->gid) < 0) { LogError("initgroups for \"%s\" failed, errno=%d\n", name, errno); return (0); } #endif /* QNX4 doesn't support multi-groups, no initgroups() */ #ifdef USE_PAM if (thepamh()) { pam_setcred(thepamh(), PAM_ESTABLISH_CRED); } #endif if (setuid(verify->uid) < 0) { LogError("setuid %d (user \"%s\") failed, errno=%d\n", verify->uid, name, errno); return (0); } #else /* HAS_SETUSERCONTEXT */ /* * Set the user's credentials: uid, gid, groups, * environment variables, resource limits, and umask. */ pwd = getpwnam(name); if (pwd) { if (setusercontext(NULL, pwd, pwd->pw_uid, LOGIN_SETALL) < 0) { LogError("setusercontext for \"%s\" failed, errno=%d\n", name, errno); return (0); } endpwent(); } else { LogError("getpwnam for \"%s\" failed, errno=%d\n", name, errno); return (0); } #endif /* HAS_SETUSERCONTEXT */ #else /* AIXV3 */ /* * Set the user's credentials: uid, gid, groups, * audit classes, user limits, and umask. */ if (setpcred(name, NULL) == -1) { LogError("setpcred for \"%s\" failed, errno=%d\n", name, errno); return (0); } #endif /* AIXV3 */ /* * for user-based authorization schemes, * use the password to get the user's credentials. */ #ifdef SECURE_RPC /* do like "keylogin" program */ { char netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1]; int nameret, keyret; int len; int key_set_ok = 0; nameret = getnetname (netname); Debug ("User netname: %s\n", netname); len = strlen (passwd); if (len > 8) bzero (passwd + 8, len - 8); keyret = getsecretkey(netname,secretkey,passwd); Debug ("getsecretkey returns %d, key length %d\n", keyret, strlen (secretkey)); /* is there a key, and do we have the right password? */ if (keyret == 1) { if (*secretkey) { keyret = key_setsecret(secretkey); Debug ("key_setsecret returns %d\n", keyret); if (keyret == -1) LogError ("failed to set NIS secret key\n"); else key_set_ok = 1; } else { /* found a key, but couldn't interpret it */ LogError ("password incorrect for NIS principal \"%s\"\n", nameret ? netname : name); } } if (!key_set_ok) { /* remove SUN-DES-1 from authorizations list */ int i, j; for (i = 0; i < d->authNum; i++) { if (d->authorizations[i]->name_length == 9 && memcmp(d->authorizations[i]->name, "SUN-DES-1", 9) == 0) { for (j = i+1; j < d->authNum; j++) d->authorizations[j-1] = d->authorizations[j]; d->authNum--; break; } } } bzero(secretkey, strlen(secretkey)); } #endif #ifdef K5AUTH /* do like "kinit" program */ { int i, j; int result; extern char *Krb5CCacheName(); result = Krb5Init(name, passwd, d); if (result == 0) { /* point session clients at the Kerberos credentials cache */ verify->userEnviron = setEnv(verify->userEnviron, "KRB5CCNAME", Krb5CCacheName(d->name)); } else { for (i = 0; i < d->authNum; i++) { if (d->authorizations[i]->name_length == 14 && memcmp(d->authorizations[i]->name, "MIT-KERBEROS-5", 14) == 0) { /* remove Kerberos from authorizations list */ for (j = i+1; j < d->authNum; j++) d->authorizations[j-1] = d->authorizations[j]; d->authNum--; break; } } } } #endif /* K5AUTH */ bzero(passwd, strlen(passwd)); SetUserAuthorization (d, verify); home = getEnv (verify->userEnviron, "HOME"); if (home) if (chdir (home) == -1) { LogError ("user \"%s\": cannot chdir to home \"%s\" (err %d), using \"/\"\n", getEnv (verify->userEnviron, "USER"), home, errno); chdir ("/"); verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/"); } if (verify->argv) { Debug ("executing session %s\n", verify->argv[0]); execute (verify->argv, verify->userEnviron); LogError ("Session \"%s\" execution failed (err %d)\n", verify->argv[0], errno); } else { LogError ("Session has no command/arguments\n"); } failsafeArgv[0] = d->failsafeClient; failsafeArgv[1] = 0; execute (failsafeArgv, verify->userEnviron); exit (1); case -1: bzero(passwd, strlen(passwd)); Debug ("StartSession, fork failed\n"); LogError ("can't start session on \"%s\", fork failed, errno=%d\n", d->name, errno); return 0; default: bzero(passwd, strlen(passwd)); Debug ("StartSession, fork succeeded %d\n", pid); *pidp = pid; return 1; } }
/* * Try to get root's secret key, by prompting if terminal is a tty, else trying * from standard input. * Returns 1 on success. */ static int getrootkey(des_block *master, int prompt) { char *passwd; char name[MAXNETNAMELEN + 1]; char secret[HEXKEYBYTES]; key_netstarg netstore; int fd; if (!prompt) { /* * Read secret key out of ROOTKEY */ fd = open(ROOTKEY, O_RDONLY, 0); if (fd < 0) { randomize(master); return (0); } if (read(fd, secret, HEXKEYBYTES) < HEXKEYBYTES) { warnx("the key read from %s was too short", ROOTKEY); close(fd); return (0); } close(fd); if (!getnetname(name)) { warnx( "failed to generate host's netname when establishing root's key"); return (0); } memcpy(netstore.st_priv_key, secret, HEXKEYBYTES); memset(netstore.st_pub_key, 0, HEXKEYBYTES); netstore.st_netname = name; if (pk_netput(0, &netstore) != KEY_SUCCESS) { warnx("could not set root's key and netname"); return (0); } return (1); } /* * Decrypt yellow pages publickey entry to get secret key */ passwd = getpass("root password:"******"can't find %s's secret key", name); return (0); } if (secret[0] == 0) { warnx("password does not decrypt secret key for %s", name); return (0); } pk_setkey(0, secret); /* * Store it for future use in $ROOTKEY, if possible */ fd = open(ROOTKEY, O_WRONLY|O_TRUNC|O_CREAT, 0); if (fd > 0) { char newline = '\n'; write(fd, secret, strlen(secret)); write(fd, &newline, sizeof (newline)); close(fd); } return (1); }
int startClient( volatile int *pid ) { const char *home, *sessargs, *desksess; char **env, *xma; char **argv, *fname, *str; #ifdef USE_PAM char ** volatile pam_env; # ifndef HAVE_PAM_GETENVLIST char **saved_env; # endif int pretc; #else # ifdef _AIX char *msg; char **theenv; extern char **newenv; /* from libs.a, this is set up by setpenv */ # endif #endif #ifdef HAVE_SETUSERCONTEXT extern char **environ; #endif char *failsafeArgv[2]; char *buf, *buf2; int i; if (strCmp( dmrcuser, curuser )) { if (curdmrc) { free( curdmrc ); curdmrc = 0; } if (dmrcuser) { free( dmrcuser ); dmrcuser = 0; } } #if defined(USE_PAM) || defined(_AIX) if (!(p = getpwnam( curuser ))) { logError( "getpwnam(%s) failed.\n", curuser ); pError: displayStr( V_MSG_ERR, 0 ); return 0; } #endif #ifndef USE_PAM # ifdef _AIX msg = NULL; loginsuccess( curuser, hostname, tty, &msg ); if (msg) { debug( "loginsuccess() - %s\n", msg ); free( (void *)msg ); } # else /* _AIX */ # if defined(KERBEROS) && defined(AFS) if (krbtkfile[0] != '\0') { if (k_hasafs()) { int fail = 0; if (k_setpag() == -1) { logError( "setpag() for %s failed\n", curuser ); fail = 1; } if ((ret = k_afsklog( NULL, NULL )) != KSUCCESS) { logError( "AFS Warning: %s\n", krb_get_err_text( ret ) ); fail = 1; } if (fail) displayMsg( V_MSG_ERR, "Warning: Problems during Kerberos4/AFS setup." ); } } # endif /* KERBEROS && AFS */ # endif /* _AIX */ #endif /* !PAM */ curuid = p->pw_uid; curgid = p->pw_gid; env = baseEnv( curuser ); xma = 0; strApp( &xma, "method=", curtype, (char *)0 ); if (td_setup) strApp( &xma, ",auto", (char *)0 ); if (xma) { env = setEnv( env, "XDM_MANAGED", xma ); free( xma ); } if (td->autoLock && cursource == PWSRC_AUTOLOGIN) env = setEnv( env, "DESKTOP_LOCKED", "true" ); env = setEnv( env, "PATH", curuid ? td->userPath : td->systemPath ); env = setEnv( env, "SHELL", p->pw_shell ); env = setEnv( env, "HOME", p->pw_dir ); #if !defined(USE_PAM) && !defined(_AIX) && defined(KERBEROS) if (krbtkfile[0] != '\0') env = setEnv( env, "KRBTKFILE", krbtkfile ); #endif userEnviron = inheritEnv( env, envvars ); env = systemEnv( curuser ); systemEnviron = setEnv( env, "HOME", p->pw_dir ); debug( "user environment:\n%[|''>'\n's" "system environment:\n%[|''>'\n's" "end of environments\n", userEnviron, systemEnviron ); /* * for user-based authorization schemes, * add the user to the server's allowed "hosts" list. */ for (i = 0; i < td->authNum; i++) { #ifdef SECURE_RPC if (td->authorizations[i]->name_length == 9 && !memcmp( td->authorizations[i]->name, "SUN-DES-1", 9 )) { XHostAddress addr; char netname[MAXNETNAMELEN+1]; char domainname[MAXNETNAMELEN+1]; getdomainname( domainname, sizeof(domainname) ); user2netname( netname, curuid, domainname ); addr.family = FamilyNetname; addr.length = strlen( netname ); addr.address = netname; XAddHost( dpy, &addr ); } #endif #ifdef K5AUTH if (td->authorizations[i]->name_length == 14 && !memcmp( td->authorizations[i]->name, "MIT-KERBEROS-5", 14 )) { /* Update server's auth file with user-specific info. * Don't need to AddHost because X server will do that * automatically when it reads the cache we are about * to point it at. */ XauDisposeAuth( td->authorizations[i] ); td->authorizations[i] = krb5GetAuthFor( 14, "MIT-KERBEROS-5", td->name ); saveServerAuthorizations( td, td->authorizations, td->authNum ); } #endif } if (*dmrcDir) mergeSessionArgs( TRUE ); debug( "now starting the session\n" ); #ifdef USE_PAM # ifdef HAVE_SETUSERCONTEXT if (setusercontext( lc, p, p->pw_uid, LOGIN_SETGROUP )) { logError( "setusercontext(groups) for %s failed: %m\n", curuser ); goto pError; } # else if (!setGid( curuser, curgid )) goto pError; # endif # ifndef HAVE_PAM_GETENVLIST if (!(pam_env = initStrArr( 0 ))) { resetGids(); goto pError; } saved_env = environ; environ = pam_env; # endif removeCreds = 1; /* set it first - i don't trust PAM's rollback */ pretc = pam_setcred( pamh, 0 ); reInitErrorLog(); # ifndef HAVE_PAM_GETENVLIST pam_env = environ; environ = saved_env; # endif # ifdef HAVE_INITGROUPS /* This seems to be a strange place for it, but do it: - after the initial groups are set - after pam_setcred might have set something, even in the error case - before pam_setcred(DELETE_CRED) might need it */ if (!saveGids()) goto pError; # endif if (pretc != PAM_SUCCESS) { logError( "pam_setcred() for %s failed: %s\n", curuser, pam_strerror( pamh, pretc ) ); resetGids(); return 0; } removeSession = 1; /* set it first - same as above */ pretc = pam_open_session( pamh, 0 ); reInitErrorLog(); if (pretc != PAM_SUCCESS) { logError( "pam_open_session() for %s failed: %s\n", curuser, pam_strerror( pamh, pretc ) ); resetGids(); return 0; } /* we don't want sessreg and the startup/reset scripts run with user credentials. unfortunately, we can reset only the gids. */ resetGids(); # define D_LOGIN_SETGROUP LOGIN_SETGROUP #else /* USE_PAM */ # define D_LOGIN_SETGROUP 0 #endif /* USE_PAM */ removeAuth = 1; chownCtrl( &td->ctrl, curuid ); endpwent(); #if !defined(USE_PAM) && defined(USESHADOW) && !defined(_AIX) endspent(); #endif ctltalk.pipe = &ctlpipe; ASPrintf( &buf, "sub-daemon for display %s", td->name ); ASPrintf( &buf2, "client for display %s", td->name ); switch (gFork( &ctlpipe, buf, buf2, 0, 0, mstrtalk.pipe, pid )) { case 0: gCloseOnExec( ctltalk.pipe ); if (Setjmp( ctltalk.errjmp )) exit( 1 ); gCloseOnExec( mstrtalk.pipe ); if (Setjmp( mstrtalk.errjmp )) goto cError; #ifndef NOXDMTITLE setproctitle( "%s'", td->name ); #endif strApp( &prog, " '", (char *)0 ); reInitErrorLog(); setsid(); sessreg( td, getpid(), curuser, curuid ); /* We do this here, as we want to have the session as parent. */ switch (source( systemEnviron, td->startup, td_setup )) { case 0: break; case wcCompose( 0, 0, 127 ): goto cError; default: /* Explicit failure => message already displayed. */ logError( "Startup script returned non-zero exit code\n" ); exit( 1 ); } /* Memory leaks are ok here as we exec() soon. */ #if defined(USE_PAM) || !defined(_AIX) # ifdef USE_PAM /* pass in environment variables set by libpam and modules it called */ # ifdef HAVE_PAM_GETENVLIST pam_env = pam_getenvlist( pamh ); reInitErrorLog(); # endif if (pam_env) for (; *pam_env; pam_env++) userEnviron = putEnv( *pam_env, userEnviron ); # endif # ifdef HAVE_SETLOGIN if (setlogin( curuser ) < 0) { logError( "setlogin for %s failed: %m\n", curuser ); goto cError; } # define D_LOGIN_SETLOGIN LOGIN_SETLOGIN # else # define D_LOGIN_SETLOGIN 0 # endif # if defined(USE_PAM) && defined(HAVE_INITGROUPS) if (!restoreGids()) goto cError; # endif # ifndef HAVE_SETUSERCONTEXT # ifdef USE_PAM if (!setUid( curuser, curuid )) goto cError; # else if (!setUser( curuser, curuid, curgid )) goto cError; # endif # else /* !HAVE_SETUSERCONTEXT */ /* * Destroy environment. * We need to do this before setusercontext() because that may * set or reset some environment variables. */ if (!(environ = initStrArr( 0 ))) goto cError; /* * Set the user's credentials: uid, gid, groups, * environment variables, resource limits, and umask. */ if (setusercontext( lc, p, p->pw_uid, LOGIN_SETALL & ~(D_LOGIN_SETGROUP|D_LOGIN_SETLOGIN) ) < 0) { logError( "setusercontext for %s failed: %m\n", curuser ); goto cError; } for (i = 0; environ[i]; i++) userEnviron = putEnv( environ[i], userEnviron ); # endif /* !HAVE_SETUSERCONTEXT */ #else /* PAM || !_AIX */ /* * Set the user's credentials: uid, gid, groups, * audit classes, user limits, and umask. */ if (setpcred( curuser, NULL ) == -1) { logError( "setpcred for %s failed: %m\n", curuser ); goto cError; } /* * Set the users process environment. Store protected variables and * obtain updated user environment list. This call will initialize * global 'newenv'. */ if (setpenv( curuser, PENV_INIT | PENV_ARGV | PENV_NOEXEC, userEnviron, NULL ) != 0) { logError( "Cannot set %s's process environment\n", curuser ); goto cError; } userEnviron = newenv; #endif /* _AIX */ /* * for user-based authorization schemes, * use the password to get the user's credentials. */ #ifdef SECURE_RPC /* do like "keylogin" program */ if (!curpass[0]) logInfo( "No password for NIS provided.\n" ); else { char netname[MAXNETNAMELEN+1], secretkey[HEXKEYBYTES+1]; int nameret, keyret; int len; int key_set_ok = 0; struct key_netstarg netst; nameret = getnetname( netname ); debug( "user netname: %s\n", netname ); len = strlen( curpass ); if (len > 8) bzero( curpass + 8, len - 8 ); keyret = getsecretkey( netname, secretkey, curpass ); debug( "getsecretkey returns %d, key length %d\n", keyret, strlen( secretkey ) ); netst.st_netname = netname; memcpy( netst.st_priv_key, secretkey, HEXKEYBYTES ); memset( netst.st_pub_key, 0, HEXKEYBYTES ); if (key_setnet( &netst ) < 0) debug( "Could not set secret key.\n" ); /* is there a key, and do we have the right password? */ if (keyret == 1) { if (*secretkey) { keyret = key_setsecret( secretkey ); debug( "key_setsecret returns %d\n", keyret ); if (keyret == -1) logError( "Failed to set NIS secret key\n" ); else key_set_ok = 1; } else { /* found a key, but couldn't interpret it */ logError( "Password incorrect for NIS principal %s\n", nameret ? netname : curuser ); } } if (!key_set_ok) nukeAuth( 9, "SUN-DES-1" ); bzero( secretkey, strlen( secretkey ) ); } #endif #ifdef K5AUTH /* do like "kinit" program */ if (!curpass[0]) logInfo( "No password for Kerberos5 provided.\n" ); else if ((str = krb5Init( curuser, curpass, td->name ))) userEnviron = setEnv( userEnviron, "KRB5CCNAME", str ); else nukeAuth( 14, "MIT-KERBEROS-5" ); #endif /* K5AUTH */ if (td->autoReLogin) { gSet( &mstrtalk ); gSendInt( D_ReLogin ); gSendStr( curuser ); gSendStr( curpass ); gSendStr( newdmrc ); } if (curpass) bzero( curpass, strlen( curpass ) ); setUserAuthorization( td ); home = getEnv( userEnviron, "HOME" ); if (home && chdir( home ) < 0) { logError( "Cannot chdir to %s's home %s: %m\n", curuser, home ); sendStr( V_MSG_ERR, "Cannot enter home directory. Using /.\n" ); chdir( "/" ); userEnviron = setEnv( userEnviron, "HOME", "/" ); home = 0; } if (home || td->clientLogFile[0] == '/') { if (!createClientLog( td->clientLogFile )) { logWarn( "Session log file according to %s cannot be created: %m\n", td->clientLogFile ); goto tmperr; } } else { tmperr: if (!createClientLog( td->clientLogFallback )) logError( "Fallback session log file according to %s cannot be created: %m\n", td->clientLogFallback ); /* Could inform the user, but I guess this is only confusing. */ } if (!*dmrcDir) mergeSessionArgs( home != 0 ); if (!(desksess = iniEntry( curdmrc, "Desktop", "Session", 0 ))) desksess = "failsafe"; /* only due to OOM */ gSet( &mstrtalk ); gSendInt( D_User ); gSendInt( curuid ); gSendStr( curuser ); gSendStr( desksess ); close( mstrtalk.pipe->fd.w ); userEnviron = setEnv( userEnviron, "DESKTOP_SESSION", desksess ); for (i = 0; td->sessionsDirs[i]; i++) { fname = 0; if (strApp( &fname, td->sessionsDirs[i], "/", desksess, ".desktop", (char *)0 )) { if ((str = iniLoad( fname ))) { if (!strCmp( iniEntry( str, "Desktop Entry", "Hidden", 0 ), "true" ) || !(sessargs = iniEntry( str, "Desktop Entry", "Exec", 0 ))) sessargs = ""; free( str ); free( fname ); goto gotit; } free( fname ); } } if (!strcmp( desksess, "failsafe" ) || !strcmp( desksess, "default" ) || !strcmp( desksess, "custom" )) sessargs = desksess; else sessargs = ""; gotit: if (!(argv = parseArgs( (char **)0, td->session )) || !(argv = addStrArr( argv, sessargs, -1 ))) exit( 1 ); if (argv[0] && *argv[0]) { debug( "executing session %\"[s\n", argv ); execute( argv, userEnviron ); logError( "Session %\"s execution failed: %m\n", argv[0] ); } else logError( "Session has no command/arguments\n" ); failsafeArgv[0] = td->failsafeClient; failsafeArgv[1] = 0; execute( failsafeArgv, userEnviron ); logError( "Failsafe client %\"s execution failed: %m\n", failsafeArgv[0] ); cError: sendStr( V_MSG_ERR, 0 ); exit( 1 ); case -1: free( buf ); return 0; } debug( "StartSession, fork succeeded %d\n", *pid ); free( buf ); gSet( &ctltalk ); if (!Setjmp( ctltalk.errjmp )) while (gRecvCmd( &i )) { buf = gRecvStr(); displayStr( i, buf ); free( buf ); gSet( &ctltalk ); gSendInt( 0 ); } gClosen( ctltalk.pipe ); finishGreet(); return 1; }