int update_keyfile(char* pw) { umask(077); FILE* f = fopen(keyfile, "w"); fprintf(f, "%d\n", now() + timeout); fprintf(f, "%d\n", getpppid()); fprintf(f, "%s\n", ttyname(0)); fprintf(f, "%d\n", getuid()); fprintf(f, "%s\n", pw); fclose(f); return 0; }
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) { FILE *file; gid_t gids[NGROUPS_MAX]; int gid_nr = 0; char buffer[MAX_STRLEN] = "", job_dir[MAX_STRLEN] = ""; static const char setup_file[] = "/var/run/sge-qrsh-setup"; if ( ! (flags & PAM_REINITIALIZE_CRED) ) return PAM_SUCCESS; /* this should find the correct file if sshd privsep is off */ sprintf(buffer, "%s.%d", setup_file, getppid()); pam_sge_log(LOG_DEBUG, "trying to open file %s", buffer); if ( ! (file = fopen(buffer, "r")) ) { /* ok - we missed it, try it again with parent's parent - sshd privsep on */ sprintf(buffer, "%s.%d", setup_file, getpppid()); pam_sge_log(LOG_DEBUG, "trying to open file %s", buffer); /* missed it again - never mind, probably there is no qrsh setup running at all... */ if ( ! (file = fopen(buffer, "r")) ) return PAM_SUCCESS; } /* read the job spool directory */ if ( fgets(job_dir, MAX_STRLEN, file) == NULL ) { fclose(file); return PAM_SYSTEM_ERR; } fclose(file); job_dir[strlen(job_dir)-1] = '\0'; /* find the file where SGE's additional group id is stored in */ snprintf(buffer, MAX_STRLEN, "%s/addgrpid", job_dir); if ( ! (file = fopen(buffer, "r")) ) return PAM_SYSTEM_ERR; /* read the id */ if ( fgets(buffer, MAX_STRLEN, file) == NULL ) { fclose(file); return PAM_SYSTEM_ERR; } fclose(file); /* fetch the groups this process is member of */ if ( (gid_nr = getgroups(NGROUPS_MAX, gids)) == -1 ) return PAM_SYSTEM_ERR; /* extract the group id into the groups field */ if ( ! sscanf(buffer, "%d", &gids[gid_nr]) ) return PAM_ABORT; setgroups(gid_nr+1, gids); /* get the job's environment variables */ snprintf(buffer, MAX_STRLEN, "%s/environment", job_dir); if ( ! (file = fopen(buffer, "r")) ) return PAM_SYSTEM_ERR; while ( fgets(buffer, MAX_STRLEN, file) ) { /* don't set SGE's wrong DISPLAY value... */ if ( strncmp(buffer, "DISPLAY=", 8) == 0 ) continue; /* remove newline at the end of buffer */ buffer[strlen(buffer)-1] = '\0'; pam_putenv(pamh, buffer); } fclose(file); return PAM_SUCCESS; }
int main(int argc, char* argv[]) { // Assemble the key file name char* homedir = getenv("HOME"); int len = strlen(homedir) + 128; keyfile = malloc(len); snprintf(keyfile, len, "%s/.scache_%d", homedir, getuid()); timeout = (argc>1) ? atoi(argv[1]) : 300; if (timeout<=0) return delete_keyfile(); if (timeout>300) timeout = 300; if (geteuid()) bail("This program must be run as root."); if (!isatty(0)) bail("ERROR: STDIN is not a TTY"); if (isatty(1)) bail("ERROR: stdout is a TTY"); struct stat statbuf; loop: if (stat(keyfile, &statbuf)<0) { init_keyfile(); if (stat(keyfile, &statbuf)<0) bail("Failed to create keyfile"); } if (statbuf.st_uid) bail("ERROR: Key file is not owned by root"); if (statbuf.st_mode != 0100600) bail("ERROR: Key file has incorrect mode"); FILE* f = fopen(keyfile, "r"); if (!f) bail("Could not open keyfile."); int cnt; char* line = 0; size_t linecap; // Check the timeout if ((cnt = getline(&line, &linecap, f)) <= 0) bail("Error reading keyfile"); if (now() > atoi(line)) { fclose(f); delete_keyfile(); fprintf(stderr, "Cached pass phrase has expired.\n"); goto loop; } // Check the PPPID if ((cnt = getline(&line, &linecap, f)) <= 0) bail("Error reading keyfile"); if (getpppid() != atoi(line)) bail("PPPID mismatch"); // Check the TTY name if ((cnt = getline(&line, &linecap, f)) <= 0) bail("Error reading keyfile"); line[strlen(line)-1]=0; char* tty = ttyname(0); if (strcmp(tty, line)) bail("TTY mismatch"); // Check the UID if ((cnt = getline(&line, &linecap, f)) <= 0) bail("Error reading keyfile"); if (getuid() != atoi(line)) bail("UID mismatch"); // Everthing checks out, get the secret if ((cnt = getline(&line, &linecap, f)) <= 0) bail("Error reading keyfile"); fclose(f); line[cnt-1] = 0; // Update the time stamp update_keyfile(line); printf("%s\n", line); }