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