passprompt.c 2.4 KB

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