Advertisement
Guest User

2stage.c

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