1*a619718eSchristos 2*a619718eSchristos Support to pass the password via a pipe to the pppd 3*a619718eSchristos --------------------------------------------------- 4*a619718eSchristos 5*a619718eSchristos Arvin Schnell <arvin@suse.de> 6*a619718eSchristos 2002-02-08 7*a619718eSchristos 8*a619718eSchristos 9*a619718eSchristos1. Introduction 10*a619718eSchristos--------------- 11*a619718eSchristos 12*a619718eSchristosNormally programs like wvdial or kppp read the online password from their 13*a619718eSchristosconfig file and store them in the pap- and chap-secrets before they start the 14*a619718eSchristospppd and remove them afterwards. Sure they need special privileges to do so. 15*a619718eSchristos 16*a619718eSchristosThe passwordfd feature offers a simpler and more secure solution. The program 17*a619718eSchristosthat starts the pppd opens a pipe and writes the password into it. The pppd 18*a619718eSchristossimply reads the password from that pipe. 19*a619718eSchristos 20*a619718eSchristosThis methods is used for quite a while on SuSE Linux by the programs wvdial, 21*a619718eSchristoskppp and smpppd. 22*a619718eSchristos 23*a619718eSchristos 24*a619718eSchristos2. Example 25*a619718eSchristos---------- 26*a619718eSchristos 27*a619718eSchristosHere is a short C program that uses the passwordfd feature. It starts the pppd 28*a619718eSchristosto buildup a pppoe connection. 29*a619718eSchristos 30*a619718eSchristos 31*a619718eSchristos--snip-- 32*a619718eSchristos 33*a619718eSchristos#include <stdio.h> 34*a619718eSchristos#include <stdlib.h> 35*a619718eSchristos#include <unistd.h> 36*a619718eSchristos#include <signal.h> 37*a619718eSchristos#include <string.h> 38*a619718eSchristos#include <paths.h> 39*a619718eSchristos 40*a619718eSchristos#ifndef _PATH_PPPD 41*a619718eSchristos#define _PATH_PPPD "/usr/sbin/pppd" 42*a619718eSchristos#endif 43*a619718eSchristos 44*a619718eSchristos 45*a619718eSchristos// Of course these values can be read from a configuration file or 46*a619718eSchristos// entered in a graphical dialog. 47*a619718eSchristoschar *device = "eth0"; 48*a619718eSchristoschar *username = "1122334455661122334455660001@t-online.de"; 49*a619718eSchristoschar *password = "hello"; 50*a619718eSchristos 51*a619718eSchristospid_t pid = 0; 52*a619718eSchristos 53*a619718eSchristos 54*a619718eSchristosvoid 55*a619718eSchristossigproc (int src) 56*a619718eSchristos{ 57*a619718eSchristos fprintf (stderr, "Sending signal %d to pid %d\n", src, pid); 58*a619718eSchristos kill (pid, src); 59*a619718eSchristos exit (EXIT_SUCCESS); 60*a619718eSchristos} 61*a619718eSchristos 62*a619718eSchristos 63*a619718eSchristosvoid 64*a619718eSchristossigchild (int src) 65*a619718eSchristos{ 66*a619718eSchristos fprintf (stderr, "Daemon died\n"); 67*a619718eSchristos exit (EXIT_SUCCESS); 68*a619718eSchristos} 69*a619718eSchristos 70*a619718eSchristos 71*a619718eSchristosint 72*a619718eSchristosstart_pppd () 73*a619718eSchristos{ 74*a619718eSchristos signal (SIGINT, &sigproc); 75*a619718eSchristos signal (SIGTERM, &sigproc); 76*a619718eSchristos signal (SIGCHLD, &sigchild); 77*a619718eSchristos 78*a619718eSchristos pid = fork (); 79*a619718eSchristos if (pid < 0) { 80*a619718eSchristos fprintf (stderr, "unable to fork() for pppd: %m\n"); 81*a619718eSchristos return 0; 82*a619718eSchristos } 83*a619718eSchristos 84*a619718eSchristos if (pid == 0) { 85*a619718eSchristos 86*a619718eSchristos int i, pppd_argc = 0; 87*a619718eSchristos char *pppd_argv[20]; 88*a619718eSchristos char buffer[32] = ""; 89*a619718eSchristos int pppd_passwdfd[2]; 90*a619718eSchristos 91*a619718eSchristos for (i = 0; i < 20; i++) 92*a619718eSchristos pppd_argv[i] = NULL; 93*a619718eSchristos 94*a619718eSchristos pppd_argv[pppd_argc++] = "pppd"; 95*a619718eSchristos 96*a619718eSchristos pppd_argv[pppd_argc++] = "call"; 97*a619718eSchristos pppd_argv[pppd_argc++] = "pwfd-test"; 98*a619718eSchristos 99*a619718eSchristos // The device must be after the call, since the call loads the plugin. 100*a619718eSchristos pppd_argv[pppd_argc++] = device; 101*a619718eSchristos 102*a619718eSchristos pppd_argv[pppd_argc++] = "user"; 103*a619718eSchristos pppd_argv[pppd_argc++] = username; 104*a619718eSchristos 105*a619718eSchristos // Open a pipe to pass the password to pppd. 106*a619718eSchristos if (pipe (pppd_passwdfd) == -1) { 107*a619718eSchristos fprintf (stderr, "pipe failed: %m\n"); 108*a619718eSchristos exit (EXIT_FAILURE); 109*a619718eSchristos } 110*a619718eSchristos 111*a619718eSchristos // Of course this only works it the password is shorter 112*a619718eSchristos // than the pipe buffer. Otherwise you have to fork to 113*a619718eSchristos // prevent that your main program blocks. 114*a619718eSchristos write (pppd_passwdfd[1], password, strlen (password)); 115*a619718eSchristos close (pppd_passwdfd[1]); 116*a619718eSchristos 117*a619718eSchristos // Tell the pppd to read the password from the fd. 118*a619718eSchristos pppd_argv[pppd_argc++] = "passwordfd"; 119*a619718eSchristos snprintf (buffer, 32, "%d", pppd_passwdfd[0]); 120*a619718eSchristos pppd_argv[pppd_argc++] = buffer; 121*a619718eSchristos 122*a619718eSchristos if (execv (_PATH_PPPD, (char **) pppd_argv) < 0) { 123*a619718eSchristos fprintf (stderr, "cannot execl %s: %m\n", _PATH_PPPD); 124*a619718eSchristos exit (EXIT_FAILURE); 125*a619718eSchristos } 126*a619718eSchristos } 127*a619718eSchristos 128*a619718eSchristos pause (); 129*a619718eSchristos 130*a619718eSchristos return 1; 131*a619718eSchristos} 132*a619718eSchristos 133*a619718eSchristos 134*a619718eSchristosint 135*a619718eSchristosmain (int argc, char **argv) 136*a619718eSchristos{ 137*a619718eSchristos if (start_pppd ()) 138*a619718eSchristos exit (EXIT_SUCCESS); 139*a619718eSchristos 140*a619718eSchristos exit (EXIT_FAILURE); 141*a619718eSchristos} 142*a619718eSchristos 143*a619718eSchristos---snip--- 144*a619718eSchristos 145*a619718eSchristos 146*a619718eSchristosCopy this file to /etc/ppp/peers/pwfd-test. The plugins can't be loaded on the 147*a619718eSchristoscommand line (unless you are root) since the plugin option is privileged. 148*a619718eSchristos 149*a619718eSchristos 150*a619718eSchristos---snip--- 151*a619718eSchristos 152*a619718eSchristos# 153*a619718eSchristos# PPPoE plugin for kernel 2.4 154*a619718eSchristos# 155*a619718eSchristosplugin pppoe.so 156*a619718eSchristos 157*a619718eSchristos# 158*a619718eSchristos# This plugin enables us to pipe the password to pppd, thus we don't have 159*a619718eSchristos# to fiddle with pap-secrets and chap-secrets. The user is also passed 160*a619718eSchristos# on the command line. 161*a619718eSchristos# 162*a619718eSchristosplugin passwordfd.so 163*a619718eSchristos 164*a619718eSchristosnoauth 165*a619718eSchristosusepeerdns 166*a619718eSchristosdefaultroute 167*a619718eSchristoshide-password 168*a619718eSchristosnodetach 169*a619718eSchristosnopcomp 170*a619718eSchristosnovjccomp 171*a619718eSchristosnoccp 172*a619718eSchristos 173*a619718eSchristos---snip--- 174*a619718eSchristos 175