Add full PAM support for account management and sessions to su(1).
[dragonfly.git] / lib / libskey / skeysubr.c
1 /* $FreeBSD: src/lib/libskey/skeysubr.c,v 1.9.6.1 2000/07/20 20:13:42 obrien Exp $ */
2 /* $DragonFly: src/lib/libskey/skeysubr.c,v 1.4 2008/09/30 16:57:06 swildner Exp $ */
3
4 #include <err.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <fcntl.h>
9 #include <termios.h>
10 #include <signal.h>
11
12 #include "skey.h"
13 #include "mdx.h"
14
15 /* Crunch a key:
16  * concatenate the seed and the password, run through MDX and
17  * collapse to 64 bits. This is defined as the user's starting key.
18  *
19  * result  8-byte result
20  * seed    Seed, any length
21  * passwd  Password, any length
22  */
23 int
24 keycrunch(char *result, const char *seed, const char *passwd)
25 {
26         char *buf;
27         MDX_CTX md;
28         u_int32_t results[4];
29         unsigned int buflen;
30
31         buflen = strlen(seed) + strlen(passwd);
32         if((buf = malloc(buflen+1)) == NULL)
33                 return -1;
34         strcpy(buf,seed);
35         strcat(buf,passwd);
36
37         /* Crunch the key through MD[45] */
38         sevenbit(buf);
39         MDXInit(&md);
40         MDXUpdate(&md,(unsigned char *)buf,buflen);
41         MDXFinal((unsigned char *)results,&md);
42         free(buf);
43
44         results[0] ^= results[2];
45         results[1] ^= results[3];
46
47         memcpy(result,(char *)results,8);
48
49         return 0;
50 }
51
52 /* The one-way function f(). Takes 8 bytes and returns 8 bytes in place */
53 void
54 f(char *x)
55 {
56         MDX_CTX md;
57         u_int32_t results[4];
58
59         MDXInit(&md);
60         MDXUpdate(&md,(unsigned char *)x,8);
61         MDXFinal((unsigned char *)results,&md);
62         /* Fold 128 to 64 bits */
63         results[0] ^= results[2];
64         results[1] ^= results[3];
65
66         memcpy(x,(char *)results,8);
67 }
68
69 /* Strip trailing cr/lf from a line of text */
70 void
71 rip(char *buf)
72 {
73         buf[strcspn(buf, "\r\n")] = 0;
74 }
75
76 static struct termios saved_ttymode;
77
78 static void interrupt (int);
79
80 static void
81 interrupt(int sig)
82 {
83         tcsetattr(0, TCSANOW, &saved_ttymode);
84         err(1, "interrupted by signal %s", sys_siglist[sig]);
85 }
86
87 char *
88 readpass(char *buf, int n)
89 {
90         struct termios noecho_ttymode;
91         void (*oldsig) (int);
92
93         /* Save normal line editing modes */
94         tcgetattr(0, &saved_ttymode);
95         if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN)
96                 signal(SIGINT, interrupt);
97
98         /* Turn off echoing */
99         tcgetattr(0, &noecho_ttymode);
100         noecho_ttymode.c_lflag &= ~ECHO;
101         tcsetattr(0, TCSANOW, &noecho_ttymode);
102         fgets(buf,n,stdin);
103         rip(buf);
104
105         /* Restore previous tty modes */
106         tcsetattr(0, TCSANOW, &saved_ttymode);
107         if (oldsig != SIG_IGN)
108                 signal(SIGINT, oldsig);
109
110         /*
111         after the secret key is taken from the keyboard, the line feed is
112         written to standard error instead of standard output.  That means that
113         anyone using the program from a terminal won't notice, but capturing
114         standard output will get the key words without a newline in front of
115         them.
116         */
117         fprintf(stderr, "\n");
118         fflush(stderr);
119         sevenbit(buf);
120
121         return buf;
122 }
123
124 void
125 sevenbit(char *s)
126 {
127         /* make sure there are only 7 bit code in the line*/
128         while(*s){
129                 *s &= 0x7f;
130                 s++;
131         }
132 }