From 5012ee48c54b55f1f5661666b362c65e417c62b7 Mon Sep 17 00:00:00 2001 From: Michal Ostrowski Date: Tue, 12 Feb 2002 00:55:25 +0000 Subject: [PATCH] Plugin for supplying CHAP password via a dedicated fd. (Arvin Schnell ) --- README.pwfd | 174 ++++++++++++++++++++++++++++++++++++ pppd/plugins/Makefile.linux | 4 +- pppd/plugins/passwordfd.c | 82 +++++++++++++++++ 3 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 README.pwfd create mode 100644 pppd/plugins/passwordfd.c diff --git a/README.pwfd b/README.pwfd new file mode 100644 index 0000000..aff87df --- /dev/null +++ b/README.pwfd @@ -0,0 +1,174 @@ + + Support to pass the password via a pipe to the pppd + --------------------------------------------------- + + Arvin Schnell + 2002-02-08 + + +1. Introduction +--------------- + +Normally programs like wvdial or kppp read the online password from their +config file and store them in the pap- and chap-secrets before they start the +pppd and remove them afterwards. Sure they need special privileges to do so. + +The passwordfd feature offers a simpler and more secure solution. The program +that starts the pppd opens a pipe and writes the password into it. The pppd +simply reads the password from that pipe. + +This methods is used for quiet a while on SuSE Linux by the programs wvdial, +kppp and smpppd. + + +2. Example +---------- + +Here is a short C program that uses the passwordfd feature. It starts the pppd +to buildup a pppoe connection. + + +--snip-- + +#include +#include +#include +#include +#include +#include + +#ifndef _PATH_PPPD +#define _PATH_PPPD "/usr/sbin/pppd" +#endif + + +// Of course these values can be read from a configuration file or +// entered in a graphical dialog. +char *device = "eth0"; +char *username = "1122334455661122334455660001@t-online.de"; +char *password = "hello"; + +pid_t pid = 0; + + +void +sigproc (int src) +{ + fprintf (stderr, "Sending signal %d to pid %d\n", src, pid); + kill (pid, src); + exit (EXIT_SUCCESS); +} + + +void +sigchild (int src) +{ + fprintf (stderr, "Daemon died\n"); + exit (EXIT_SUCCESS); +} + + +int +start_pppd () +{ + signal (SIGINT, &sigproc); + signal (SIGTERM, &sigproc); + signal (SIGCHLD, &sigchild); + + pid = fork (); + if (pid < 0) { + fprintf (stderr, "unable to fork() for pppd: %m\n"); + return 0; + } + + if (pid == 0) { + + int i, pppd_argc = 0; + char *pppd_argv[20]; + char buffer[32] = ""; + int pppd_passwdfd[2]; + + for (i = 0; i < 20; i++) + pppd_argv[i] = NULL; + + pppd_argv[pppd_argc++] = "pppd"; + + pppd_argv[pppd_argc++] = "call"; + pppd_argv[pppd_argc++] = "pwfd-test"; + + // The device must be after the call, since the call loads the plugin. + pppd_argv[pppd_argc++] = device; + + pppd_argv[pppd_argc++] = "user"; + pppd_argv[pppd_argc++] = username; + + // Open a pipe to pass the password to pppd. + if (pipe (pppd_passwdfd) == -1) { + fprintf (stderr, "pipe failed: %m\n"); + exit (EXIT_FAILURE); + } + + // Of course this only works it the password is shorter + // than the pipe buffer. Otherwise you have to fork to + // prevent that your main program blocks. + write (pppd_passwdfd[1], password, strlen (password)); + close (pppd_passwdfd[1]); + + // Tell the pppd to read the password from the fd. + pppd_argv[pppd_argc++] = "passwordfd"; + snprintf (buffer, 32, "%d", pppd_passwdfd[0]); + pppd_argv[pppd_argc++] = buffer; + + if (execv (_PATH_PPPD, (char **) pppd_argv) < 0) { + fprintf (stderr, "cannot execl %s: %m\n", _PATH_PPPD); + exit (EXIT_FAILURE); + } + } + + pause (); + + return 1; +} + + +int +main (int argc, char **argv) +{ + if (start_pppd ()) + exit (EXIT_SUCCESS); + + exit (EXIT_FAILURE); +} + +---snip--- + + +Copy this file to /etc/ppp/peers/pwfd-test. The plugins can't be loaded on the +command line (unless you are root) since the plugin option is privileged. + + +---snip--- + +# +# PPPoE plugin for kernel 2.4 +# +plugin pppoe.so + +# +# This plugin enables us to pipe the password to pppd, thus we don't have +# to fiddle with pap-secrets and chap-secrets. The user is also passed +# on the command line. +# +plugin passwordfd.so + +noauth +usepeerdns +defaultroute +hide-password +nodetach +nopcomp +novjccomp +noccp + +---snip--- + diff --git a/pppd/plugins/Makefile.linux b/pppd/plugins/Makefile.linux index 7cdfe42..1cf721a 100644 --- a/pppd/plugins/Makefile.linux +++ b/pppd/plugins/Makefile.linux @@ -4,7 +4,7 @@ LDFLAGS = -shared INSTALL = install -o root SUBDIRS = rp-pppoe radius -PLUGINS = minconn.so passprompt.so +PLUGINS = minconn.so passprompt.so passwordfd.so # include dependencies if present ifeq (.depend,$(wildcard .depend)) @@ -18,7 +18,7 @@ all: $(PLUGINS) $(CC) -o $@ $(LDFLAGS) $(CFLAGS) $^ VERSION = $(shell awk -F '"' '/VERSION/ { print $$2; }' ../patchlevel.h) -LIBDIR = $(DESTDIR)/usr/lib/pppd/$(VERSION) +LIBDIR = $(DESTDIR)/lib/pppd/$(VERSION) install: $(PLUGINS) $(INSTALL) -d $(LIBDIR) diff --git a/pppd/plugins/passwordfd.c b/pppd/plugins/passwordfd.c new file mode 100644 index 0000000..d718f3b --- /dev/null +++ b/pppd/plugins/passwordfd.c @@ -0,0 +1,82 @@ + +/* + * Author: Arvin Schnell + * + * This plugin let's you pass the password to the pppd via + * a file descriptor. That's easy and secure - no fiddling + * with pap- and chap-secrets files. + */ + +#include +#include +#include +#include + +#include "pppd.h" + +char pppd_version[] = VERSION; + +static int passwdfd = -1; +static char save_passwd[MAXSECRETLEN]; + +static option_t options[] = { + { "passwordfd", o_int, &passwdfd, + "Receive password on this file descriptor" }, + { NULL } +}; + +static int pwfd_check (void) +{ + return 1; +} + +static int pwfd_passwd (char *user, char *passwd) +{ + int readgood, red; + + if (passwdfd == -1) + return -1; + + if (passwd == NULL) + return 1; + + if (passwdfd == -2) { + strcpy (passwd, save_passwd); + return 1; + } + + readgood = 0; + do { + red = read (passwdfd, passwd + readgood, MAXSECRETLEN - 1 - readgood); + if (red == 0) + break; + if (red < 0) { + error ("Can't read secret from fd\n"); + readgood = -1; + break; + } + readgood += red; + } while (readgood < MAXSECRETLEN - 1); + + close (passwdfd); + + if (readgood < 0) + return 0; + + passwd[readgood] = 0; + strcpy (save_passwd, passwd); + passwdfd = -2; + + return 1; +} + +void plugin_init (void) +{ + add_options (options); + + pap_check_hook = pwfd_check; + pap_passwd_hook = pwfd_passwd; + + chap_check_hook = pwfd_check; + chap_passwd_hook = pwfd_passwd; +} -- 2.39.2