Guest User

2stage.c

a guest
Jul 4th, 2012
2,345
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.04 KB | None | 0 0
  1. /* 2stage v0
  2.  * ---
  3.  * Zachary Hamm
  4.  *
  5.  * I often have to ssh into systems from untrusted public computers. The
  6.  * possibility of keyloggers makes me nervous (I'm the paranoid sort). I could
  7.  * use an ssh key on a usb drive or somesuch but that's often not an option,
  8.  * (plus, it's a nuisance to carry a precious usb drive around when I've got
  9.  * my passwords all stored up in my noggin). So I use password authentication.
  10.  * But those keyloggers torment me... keep me up at night...
  11.  *
  12.  * Googles two-stage auth  gives me the confidence to read my email at a public
  13.  * computer. I made this so I could have the same confidence when ssh'ing
  14.  * into my servers.
  15.  *
  16.  * Installation (requires libcurl and libreadline):
  17.  *   1. Edit the #defines below for yourself.
  18.  *   2. Build with cc 2stage.c -o 2stage -lcurl -lreadline
  19.  *   3. Move to /bin or some such.
  20.  *   4. Add /bin/2stage to /etc/shells
  21.  *   5. Edit /etc/passwd and set your shell to /bin/2stage
  22.  * And that's it. Try ssh'ing in.
  23.  *
  24.  *
  25.  * TODO: * Make it configurable by each user via a dotfile in the home dir.
  26.  *       * Option to remember trusted hosts for 30 days so you don't
  27.  *      have to do this over and over from your main boxen.
  28.  *       * Add logging of failed passcode attempts.
  29.  *   * Does this break X11 forwarding? Must test.
  30.  *   * Once all that is done, give it a proper autoconf and git host
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include <fcntl.h>
  39. #include <errno.h>
  40.  
  41. #include <curl/curl.h>
  42. #include <readline/readline.h>
  43. #include <readline/history.h>
  44.  
  45. #define MSG "From: %s\r\nTo: %s\r\n\r\nYour two-stage passcode is %d\r\n"
  46.  
  47. /* Configuration happens here */
  48.  
  49. /* You */
  50. #define FROM "<[email protected]>"
  51.  
  52. /* Your SMS gateway or an email address if you don't want to use a phone */
  53. #define TO "<[email protected]>"
  54.  
  55. /* Set your preferred shell here */
  56. #define CONCH "/bin/bash"
  57.  
  58. int executeur(int argc, char **argv);
  59. unsigned int stupid_random(void);
  60. size_t mailbody(void *ptr, size_t size, size_t nitems, void *strm);
  61. int send_passcode(void);
  62.  
  63. static unsigned int passcode;
  64.  
  65. int executeur(int argcount, char **argvee)
  66. {
  67.     char **args = (char **)malloc(sizeof(char *) * (argcount + 1));
  68.     int i;
  69.  
  70.     args[0] = CONCH;
  71.     for(i = 1 ; i < argcount ; i++)
  72.     {
  73.         args[i] = argvee[i];
  74.     }
  75.     args[argcount] = NULL;
  76.  
  77.     return execv(args[0], args);
  78. }
  79.  
  80. unsigned int stupid_random(void)
  81. {
  82.     int urandom_fd;
  83.     unsigned int randy = 0;
  84.  
  85.     urandom_fd = open("/dev/urandom", O_RDONLY);
  86.  
  87.     /* We want a number between 10^6 and 10^7 so that we get a 6 digit
  88.        number */
  89.     while (!(randy > (1000000 - 1) && randy < (10000000 - 1)))
  90.     {
  91.         /* read 3 bytes intead of 4 to insure less hits over
  92.            the threshold (so we get our random number faster) */
  93.         read(urandom_fd, &randy, sizeof(unsigned int)-1);
  94.     }
  95.  
  96.     close(urandom_fd);
  97.  
  98.     return (unsigned int)randy;
  99. }
  100.  
  101.  
  102. /* Callback for CURLOPT_READFUNCTION */
  103. size_t mailbody(void *ptr, size_t size, size_t nitems, void *strm)
  104. {
  105.     static unsigned int dirty = 0;
  106.     char *s;
  107.     size_t len = 0;
  108.  
  109.     if(!dirty)
  110.     {
  111.         /* 6 is the digit length of the ints from stupid_random()
  112.            XXX: we assume malloc succeeds. this is sloppy. */
  113.         s = (char *) malloc(strlen(MSG)+strlen(FROM)+strlen(TO)+6+1);
  114.         passcode = stupid_random();
  115.         sprintf(s, MSG, FROM, TO, passcode);
  116.         len = strlen(s);
  117.         memcpy(ptr, s, len);
  118.         dirty = 1;
  119.         free(s);
  120.  
  121.         return len;
  122.     }
  123.  
  124.     return 0;
  125. }
  126.  
  127. int send_passcode(void)
  128. {
  129.     CURL *curl;
  130.     CURLcode res;
  131.     struct curl_slist *targets = NULL;
  132.    
  133.     curl = curl_easy_init();
  134.     if (!curl) {
  135.         printf("Something bad happened to curl_easy_init()!");
  136.         return -1;
  137.     }
  138.  
  139. /*  curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); */
  140.  
  141.     curl_easy_setopt(curl, CURLOPT_URL, "smtp://localhost");
  142.     targets = curl_slist_append(targets, TO);
  143.     curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, targets);
  144.     curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
  145.    
  146.     curl_easy_setopt(curl, CURLOPT_READFUNCTION, mailbody);
  147.    
  148.     res = curl_easy_perform(curl);
  149.     if(res != 0)
  150.     {
  151.         printf("Something bad happened!\n");
  152.         return -1;
  153.     }
  154.  
  155.     curl_slist_free_all(targets);
  156.     curl_easy_cleanup(curl);
  157.  
  158.     return 0;
  159. }
  160.  
  161. int main(int argc, char *argv[])
  162. {
  163.     char *input;
  164.  
  165.     printf("2stage! Sending the passcode to your phone.\n");
  166.     if(send_passcode() != 0)
  167.     {
  168.         printf("Oh no! Badness! Try again or contact the admin...");
  169.         return -1;
  170.     }  
  171.  
  172.     input = readline("Passcode sent! Have patience, then enter it: ");
  173.     if(strtol(input, NULL, 10) == passcode)
  174.     {
  175.         printf("%s == %d!\nGood job!\n", input, passcode);
  176.         free(input);
  177.     }
  178.     else
  179.     {
  180.         free(input);   
  181.         input = readline("No! Bad job! You get one more try: ");
  182.         if(strtol(input, NULL, 10) == passcode)
  183.         {
  184.             printf("Good job!\n");
  185.         }
  186.         else
  187.         {
  188.             printf("Not this time, bub.\n");
  189.             /* XXX: send textmsg about passcode failure. log it
  190.                as well */
  191.             return -1;
  192.         }
  193.  
  194.         free(input);
  195.     }
  196.  
  197.     if(executeur(argc, argv) == -1)
  198.     {
  199.         perror("execv");
  200.         return -1;
  201.     }
  202.  
  203.     return 0;
  204. }
Advertisement
Add Comment
Please, Sign In to add comment