Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* 2stage v0
- * ---
- * Zachary Hamm
- * zsh@imipolexg.org
- *
- * I often have to ssh into systems from untrusted public computers. The
- * possibility of keyloggers makes me nervous (I'm the paranoid sort). I could
- * use an ssh key on a usb drive or somesuch but that's often not an option,
- * (plus, it's a nuisance to carry a precious usb drive around when I've got
- * my passwords all stored up in my noggin). So I use password authentication.
- * But those keyloggers torment me... keep me up at night...
- *
- * Googles two-stage auth gives me the confidence to read my email at a public
- * computer. I made this so I could have the same confidence when ssh'ing
- * into my servers.
- *
- * Installation (requires libcurl and libreadline):
- * 1. Edit the #defines below for yourself.
- * 2. Build with cc 2stage.c -o 2stage -lcurl -lreadline
- * 3. Move to /bin or some such.
- * 4. Add /bin/2stage to /etc/shells
- * 5. Edit /etc/passwd and set your shell to /bin/2stage
- * And that's it. Try ssh'ing in.
- *
- *
- * TODO: * Make it configurable by each user via a dotfile in the home dir.
- * * Option to remember trusted hosts for 30 days so you don't
- * have to do this over and over from your main boxen.
- * * Add logging of failed passcode attempts.
- * * Does this break X11 forwarding? Must test.
- * * Once all that is done, give it a proper autoconf and git host
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <curl/curl.h>
- #include <readline/readline.h>
- #include <readline/history.h>
- #define MSG "From: %s\r\nTo: %s\r\n\r\nYour two-stage passcode is %d\r\n"
- /* Configuration happens here */
- /* You */
- #define FROM "<zsh@imipolexg.org>"
- /* Your SMS gateway or an email address if you don't want to use a phone */
- #define TO "<XXXXXXXX@messaging.sprintpcs.com>"
- /* Set your preferred shell here */
- #define CONCH "/bin/bash"
- int executeur(int argc, char **argv);
- unsigned int stupid_random(void);
- size_t mailbody(void *ptr, size_t size, size_t nitems, void *strm);
- int send_passcode(void);
- static unsigned int passcode;
- int executeur(int argcount, char **argvee)
- {
- char **args = (char **)malloc(sizeof(char *) * (argcount + 1));
- int i;
- args[0] = CONCH;
- for(i = 1 ; i < argcount ; i++)
- {
- args[i] = argvee[i];
- }
- args[argcount] = NULL;
- return execv(args[0], args);
- }
- unsigned int stupid_random(void)
- {
- int urandom_fd;
- unsigned int randy = 0;
- urandom_fd = open("/dev/urandom", O_RDONLY);
- /* We want a number between 10^6 and 10^7 so that we get a 6 digit
- number */
- while (!(randy > (1000000 - 1) && randy < (10000000 - 1)))
- {
- /* read 3 bytes intead of 4 to insure less hits over
- the threshold (so we get our random number faster) */
- read(urandom_fd, &randy, sizeof(unsigned int)-1);
- }
- close(urandom_fd);
- return (unsigned int)randy;
- }
- /* Callback for CURLOPT_READFUNCTION */
- size_t mailbody(void *ptr, size_t size, size_t nitems, void *strm)
- {
- static unsigned int dirty = 0;
- char *s;
- size_t len = 0;
- if(!dirty)
- {
- /* 6 is the digit length of the ints from stupid_random()
- XXX: we assume malloc succeeds. this is sloppy. */
- s = (char *) malloc(strlen(MSG)+strlen(FROM)+strlen(TO)+6+1);
- passcode = stupid_random();
- sprintf(s, MSG, FROM, TO, passcode);
- len = strlen(s);
- memcpy(ptr, s, len);
- dirty = 1;
- free(s);
- return len;
- }
- return 0;
- }
- int send_passcode(void)
- {
- CURL *curl;
- CURLcode res;
- struct curl_slist *targets = NULL;
- curl = curl_easy_init();
- if (!curl) {
- printf("Something bad happened to curl_easy_init()!");
- return -1;
- }
- /* curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); */
- curl_easy_setopt(curl, CURLOPT_URL, "smtp://localhost");
- targets = curl_slist_append(targets, TO);
- curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, targets);
- curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
- curl_easy_setopt(curl, CURLOPT_READFUNCTION, mailbody);
- res = curl_easy_perform(curl);
- if(res != 0)
- {
- printf("Something bad happened!\n");
- return -1;
- }
- curl_slist_free_all(targets);
- curl_easy_cleanup(curl);
- return 0;
- }
- int main(int argc, char *argv[])
- {
- char *input;
- printf("2stage! Sending the passcode to your phone.\n");
- if(send_passcode() != 0)
- {
- printf("Oh no! Badness! Try again or contact the admin...");
- return -1;
- }
- input = readline("Passcode sent! Have patience, then enter it: ");
- if(strtol(input, NULL, 10) == passcode)
- {
- printf("%s == %d!\nGood job!\n", input, passcode);
- free(input);
- }
- else
- {
- free(input);
- input = readline("No! Bad job! You get one more try: ");
- if(strtol(input, NULL, 10) == passcode)
- {
- printf("Good job!\n");
- }
- else
- {
- printf("Not this time, bub.\n");
- /* XXX: send textmsg about passcode failure. log it
- as well */
- return -1;
- }
- free(input);
- }
- if(executeur(argc, argv) == -1)
- {
- perror("execv");
- return -1;
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement