]> andersk Git - moira.git/blob - update/auth_002.c
Implement AUTH_002, which isn't vulnerable to replay attacks. Remove
[moira.git] / update / auth_002.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5 /*  (c) Copyright 1988 by the Massachusetts Institute of Technology. */
6 /*  For copying and distribution information, please see the file */
7 /*  <mit-copyright.h>. */
8
9 #ifndef lint
10 static char *rcsid_auth_002_c = "$Header$";
11 #endif
12
13 #include <mit-copyright.h>
14 #include <stdio.h>
15 #include <string.h>
16 #include <gdb.h>
17 #include <krb.h>
18 #include <krb_et.h>
19 #include <netinet/in.h>
20 #include <errno.h>
21 #ifdef POSIX
22 #include <sys/utsname.h>
23 #endif
24
25 extern char buf[BUFSIZ];
26 extern int have_authorization;
27 extern struct sockaddr_in *client_address();
28 extern CONNECTION conn;
29 extern int code;
30 extern char *PrincipalHostname();
31 static char service[] = "rcmd";
32 static char master[] = "sms";
33 static char qmark[] = "???";
34 extern C_Block session;
35
36 /*
37  * authentication request auth_002:
38  *
39  * >>> (STRING) "auth_002"
40  * <<< (int) 0
41  * >>> (STRING) ticket
42  * <<< (int) code
43  * <<< (STRING) nonce
44  * >>> (STRING) encrypted nonce
45  * <<< (int) code
46  *
47  */
48
49 int
50 auth_002(str)
51      char *str;
52 {
53     STRING data;
54     char host[BUFSIZ], realm[REALM_SZ];
55     char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ];
56     AUTH_DAT ad;
57     char *p, *first, *config_lookup();
58     KTEXT_ST ticket_st;
59 #ifdef POSIX
60     struct utsname name;
61 #endif
62     des_key_schedule sched;
63     C_Block nonce, nonce2;
64
65     if (send_ok())
66         lose("sending okay for authorization (auth_002)");
67     code = receive_object(conn, (char *)&data, STRING_T);
68     if (code) {
69         code = connection_errno(conn);
70         lose("awaiting Kerberos authenticators");
71     }
72 #ifdef POSIX
73     (void) uname(&name);
74     strncpy(host, name.nodename, sizeof(host));
75 #else
76     gethostname(host, sizeof(host));
77 #endif
78     ticket_st.mbz = 0;
79     ticket_st.length = MAX_STRING_SIZE(data);
80     memcpy(ticket_st.dat, STRING_DATA(data), MAX_STRING_SIZE(data));
81     code = krb_rd_req(&ticket_st, service,
82                       krb_get_phost(host), 0,
83                       &ad, KEYFILE);
84     if (code) {
85         code += ERROR_TABLE_BASE_krb;
86         strcpy(ad.pname, qmark);
87         strcpy(ad.pinst, qmark);
88         strcpy(ad.prealm, qmark);
89         goto auth_failed;
90     }
91
92     /* If there is an auth record in the config file matching the
93      * authenticator we received, then accept it.  If there's no
94      * auth record, assume [master]@[local realm].
95      */
96     if (first = p = config_lookup("auth")) {
97         do {
98             kname_parse(aname, ainst, arealm, p);
99             if (strcmp(aname, ad.pname) ||
100                 strcmp(ainst, ad.pinst) ||
101                 strcmp(arealm, ad.prealm))
102               p = config_lookup("auth");
103             else
104               p = first;
105         } while (p != first);
106     } else {
107         strcpy(aname, master);
108         strcpy(ainst, "");
109         if (krb_get_lrealm(arealm,1))
110           strcpy(arealm, KRB_REALM);
111     }
112     code = EPERM;
113     if (strcmp(aname, ad.pname) ||
114         strcmp(ainst, ad.pinst) ||
115         strcmp(arealm, ad.prealm))
116       goto auth_failed;
117
118     if (send_ok())
119         lose("sending preliminary approval of authorization");
120
121     /* replay protection */
122     des_random_key(&nonce);
123     STRING_DATA(data) = (char *)nonce;
124     MAX_STRING_SIZE(data) = 8;
125     if (send_object(conn, (char *)&data, STRING_T))
126         lose("sending nonce");
127     code = receive_object(conn, (char *)&data, STRING_T);
128     des_key_sched(&ad.session, &sched);
129     des_ecb_encrypt(STRING_DATA(data), nonce2, sched, 0);
130     if (memcmp(nonce, nonce2, sizeof(nonce)))
131         goto auth_failed;
132
133     if (send_ok())
134         lose("sending approval of authorization");
135     have_authorization = 1;
136     /* Stash away session key */
137     memcpy(session, ad.session, sizeof(session));
138     return(0);
139 auth_failed:
140     sprintf(buf, "auth for %s.%s@%s failed: %s",
141             ad.pname, ad.pinst, ad.prealm, error_message(code));
142     {
143         register int rc;
144         rc = send_object(conn, (char *)&code, INTEGER_T);
145         code = rc;
146     }
147     if (code)
148         lose("sending rejection of authenticator");
149     return(EPERM);
150 }
This page took 0.0454020000000001 seconds and 5 git commands to generate.