18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * passprompt.c - pppd plugin to invoke an external PAP password prompter
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright 1999 Paul Mackerras, Alan Curry.
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *  This program is free software; you can redistribute it and/or
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *  modify it under the terms of the GNU General Public License
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *  as published by the Free Software Foundation; either version
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *  2 of the License, or (at your option) any later version.
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <errno.h>
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <unistd.h>
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <sys/wait.h>
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <syslog.h>
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppd.h"
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar pppd_version[] = VERSION;
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic char promptprog[PATH_MAX+1];
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic option_t options[] = {
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    { "promptprog", o_string, promptprog,
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      "External PAP password prompting program",
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project      OPT_STATIC, NULL, PATH_MAX },
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    { NULL }
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project};
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int promptpass(char *user, char *passwd)
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int p[2];
318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pid_t kid;
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int readgood, wstat;
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    ssize_t red;
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (promptprog[0] == 0 || access(promptprog, X_OK) < 0)
368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return -1;	/* sorry, can't help */
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!passwd)
398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 1;
408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (pipe(p)) {
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	warn("Can't make a pipe for %s", promptprog);
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 0;
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((kid = fork()) == (pid_t) -1) {
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	warn("Can't fork to run %s", promptprog);
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	close(p[0]);
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	close(p[1]);
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 0;
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!kid) {
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* we are the child, exec the program */
531286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	char *argv[5], fdstr[32];
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sys_close();
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	closelog();
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	close(p[0]);
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	seteuid(getuid());
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	setegid(getgid());
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	argv[0] = promptprog;
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	argv[1] = user;
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	argv[2] = remote_name;
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sprintf(fdstr, "%d", p[1]);
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	argv[3] = fdstr;
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	argv[4] = 0;
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	execv(*argv, argv);
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	_exit(127);
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* we are the parent, read the password from the pipe */
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    close(p[1]);
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    readgood = 0;
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    do {
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	red = read(p[0], passwd + readgood, MAXSECRETLEN-1 - readgood);
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (red == 0)
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (red < 0) {
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (errno == EINTR)
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		continue;
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    error("Can't read secret from %s: %m", promptprog);
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    readgood = -1;
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	readgood += red;
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } while (readgood < MAXSECRETLEN - 1);
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    close(p[0]);
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    /* now wait for child to exit */
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while (waitpid(kid, &wstat, 0) < 0) {
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (errno != EINTR) {
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    warn("error waiting for %s: %m", promptprog);
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    break;
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (readgood < 0)
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return 0;
971286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley    passwd[readgood] = 0;
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (!WIFEXITED(wstat))
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	warn("%s terminated abnormally", promptprog);
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (WEXITSTATUS(wstat))
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	warn("%s exited with code %d", promptprog, WEXITSTATUS(status));
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return 1;
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid plugin_init(void)
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    add_options(options);
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    pap_passwd_hook = promptpass;
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
111