1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * passprompt.c - pppd plugin to invoke an external PAP password prompter 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * Copyright 1999 Paul Mackerras, Alan Curry. 5*7c478bd9Sstevel@tonic-gate * 6*7c478bd9Sstevel@tonic-gate * This program is free software; you can redistribute it and/or 7*7c478bd9Sstevel@tonic-gate * modify it under the terms of the GNU General Public License 8*7c478bd9Sstevel@tonic-gate * as published by the Free Software Foundation; either version 9*7c478bd9Sstevel@tonic-gate * 2 of the License, or (at your option) any later version. 10*7c478bd9Sstevel@tonic-gate */ 11*7c478bd9Sstevel@tonic-gate #include <errno.h> 12*7c478bd9Sstevel@tonic-gate #include <unistd.h> 13*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 14*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 15*7c478bd9Sstevel@tonic-gate #include <syslog.h> 16*7c478bd9Sstevel@tonic-gate #include "pppd.h" 17*7c478bd9Sstevel@tonic-gate 18*7c478bd9Sstevel@tonic-gate static char promptprog[PATH_MAX+1]; 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gate static option_t options[] = { 21*7c478bd9Sstevel@tonic-gate { "promptprog", o_string, promptprog, 22*7c478bd9Sstevel@tonic-gate "External PAP password prompting program", 23*7c478bd9Sstevel@tonic-gate OPT_STATIC, NULL, PATH_MAX }, 24*7c478bd9Sstevel@tonic-gate { NULL } 25*7c478bd9Sstevel@tonic-gate }; 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate static int promptpass(char *user, char *passwd) 28*7c478bd9Sstevel@tonic-gate { 29*7c478bd9Sstevel@tonic-gate int p[2]; 30*7c478bd9Sstevel@tonic-gate pid_t kid; 31*7c478bd9Sstevel@tonic-gate int readgood, wstat; 32*7c478bd9Sstevel@tonic-gate int red; 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate if (promptprog[0] == 0 || access(promptprog, X_OK) < 0) 35*7c478bd9Sstevel@tonic-gate return -1; /* sorry, can't help */ 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* This occurs when we're probed for the ability to supply a password */ 38*7c478bd9Sstevel@tonic-gate if (user != NULL && passwd == NULL) 39*7c478bd9Sstevel@tonic-gate return 1; 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate if (pipe(p)) { 42*7c478bd9Sstevel@tonic-gate warn("Can't make a pipe for %s", promptprog); 43*7c478bd9Sstevel@tonic-gate return 0; 44*7c478bd9Sstevel@tonic-gate } 45*7c478bd9Sstevel@tonic-gate if ((kid = fork()) == (pid_t) -1) { 46*7c478bd9Sstevel@tonic-gate warn("Can't fork to run %s", promptprog); 47*7c478bd9Sstevel@tonic-gate (void) close(p[0]); 48*7c478bd9Sstevel@tonic-gate (void) close(p[1]); 49*7c478bd9Sstevel@tonic-gate return 0; 50*7c478bd9Sstevel@tonic-gate } 51*7c478bd9Sstevel@tonic-gate if (kid == (pid_t)0) { 52*7c478bd9Sstevel@tonic-gate /* we are the child, exec the program */ 53*7c478bd9Sstevel@tonic-gate char *argv[5], fdstr[32]; 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate sys_close(); 56*7c478bd9Sstevel@tonic-gate closelog(); 57*7c478bd9Sstevel@tonic-gate if (detached && p[1] <= 2) { 58*7c478bd9Sstevel@tonic-gate (void) dup2(p[1], 3); 59*7c478bd9Sstevel@tonic-gate p[1] = 3; 60*7c478bd9Sstevel@tonic-gate } 61*7c478bd9Sstevel@tonic-gate (void) close(p[0]); 62*7c478bd9Sstevel@tonic-gate if (detached) { 63*7c478bd9Sstevel@tonic-gate red = open("/etc/ppp/prompt-errors", O_WRONLY | O_APPEND | O_CREAT, 64*7c478bd9Sstevel@tonic-gate 0600); 65*7c478bd9Sstevel@tonic-gate (void) dup2(red, 1); 66*7c478bd9Sstevel@tonic-gate (void) dup2(red, 2); 67*7c478bd9Sstevel@tonic-gate } 68*7c478bd9Sstevel@tonic-gate (void) seteuid(getuid()); 69*7c478bd9Sstevel@tonic-gate (void) setegid(getgid()); 70*7c478bd9Sstevel@tonic-gate argv[0] = promptprog; 71*7c478bd9Sstevel@tonic-gate argv[1] = user == NULL ? "" : user; 72*7c478bd9Sstevel@tonic-gate argv[2] = remote_name; 73*7c478bd9Sstevel@tonic-gate slprintf(fdstr, sizeof (fdstr), "%d", p[1]); 74*7c478bd9Sstevel@tonic-gate argv[3] = fdstr; 75*7c478bd9Sstevel@tonic-gate argv[4] = NULL; 76*7c478bd9Sstevel@tonic-gate (void) execv(*argv, argv); 77*7c478bd9Sstevel@tonic-gate _exit(127); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* we are the parent, read the password from the pipe */ 81*7c478bd9Sstevel@tonic-gate (void) close(p[1]); 82*7c478bd9Sstevel@tonic-gate readgood = 0; 83*7c478bd9Sstevel@tonic-gate do { 84*7c478bd9Sstevel@tonic-gate red = read(p[0], passwd + readgood, MAXSECRETLEN-1 - readgood); 85*7c478bd9Sstevel@tonic-gate if (red == 0) 86*7c478bd9Sstevel@tonic-gate break; 87*7c478bd9Sstevel@tonic-gate if (red < 0) { 88*7c478bd9Sstevel@tonic-gate if (errno == EINTR) 89*7c478bd9Sstevel@tonic-gate continue; 90*7c478bd9Sstevel@tonic-gate error("Can't read secret from %s: %m", promptprog); 91*7c478bd9Sstevel@tonic-gate readgood = -1; 92*7c478bd9Sstevel@tonic-gate break; 93*7c478bd9Sstevel@tonic-gate } 94*7c478bd9Sstevel@tonic-gate readgood += red; 95*7c478bd9Sstevel@tonic-gate } while (readgood < MAXSECRETLEN - 1); 96*7c478bd9Sstevel@tonic-gate passwd[readgood] = 0; 97*7c478bd9Sstevel@tonic-gate (void) close(p[0]); 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate /* now wait for child to exit */ 100*7c478bd9Sstevel@tonic-gate while (waitpid(kid, &wstat, 0) < 0) { 101*7c478bd9Sstevel@tonic-gate if (errno != EINTR) { 102*7c478bd9Sstevel@tonic-gate warn("error waiting for %s: %m", promptprog); 103*7c478bd9Sstevel@tonic-gate break; 104*7c478bd9Sstevel@tonic-gate } 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate if (readgood < 0) 108*7c478bd9Sstevel@tonic-gate return 0; 109*7c478bd9Sstevel@tonic-gate if (readgood > 0 && passwd[--readgood] == '\n') 110*7c478bd9Sstevel@tonic-gate passwd[readgood] = '\0'; 111*7c478bd9Sstevel@tonic-gate if (!WIFEXITED(wstat)) 112*7c478bd9Sstevel@tonic-gate warn("%s terminated abnormally", promptprog); 113*7c478bd9Sstevel@tonic-gate if (WEXITSTATUS(wstat) != 0) 114*7c478bd9Sstevel@tonic-gate warn("%s exited with code %d", promptprog, WEXITSTATUS(wstat)); 115*7c478bd9Sstevel@tonic-gate 116*7c478bd9Sstevel@tonic-gate return 1; 117*7c478bd9Sstevel@tonic-gate } 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gate void plugin_init(void) 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate add_options(options); 122*7c478bd9Sstevel@tonic-gate pap_passwd_hook = promptpass; 123*7c478bd9Sstevel@tonic-gate } 124