]> andersk Git - moira.git/blob - update/auth_003.c
Build without krb4 if it's unavailable.
[moira.git] / update / auth_003.c
1 /* $Id$
2  *
3  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
4  * For copying and distribution information, please see the file
5  * <mit-copyright.h>.
6  */
7
8 #include <mit-copyright.h>
9 #include <moira.h>
10 #include "update_server.h"
11
12 #include <sys/utsname.h>
13
14 #include <errno.h>
15 #include <stdio.h>
16 #include <string.h>
17
18 #ifdef HAVE_KRB4
19 #include <krb.h>
20 #else
21 #include <mr_krb.h>
22 #endif
23 #include <krb5.h>
24
25 RCSID("$Header$");
26
27 static char service[] = "host";
28 static char master[] = "sms";
29 static char qmark[] = "???";
30
31 /*
32  * authentication request auth_003:
33  *
34  * >>> (STRING) "auth_003"
35  * <<< (int) 0
36  * >>> (STRING) ticket
37  * <<< (int) code
38  *
39  */
40
41 void auth_003(int conn, char *str)
42 {
43   krb5_context context = NULL;
44   krb5_auth_context auth_con = NULL;
45   krb5_data auth;
46   krb5_principal server = NULL, client = NULL;
47   krb5_ticket *ticket;
48   char *p, *first, *data;
49   char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
50   char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ];
51   char *lrealm = NULL;
52   size_t size;
53   long code;
54   struct utsname uts;
55
56   ticket = NULL;
57
58   send_ok(conn);
59
60   recv_string(conn, &data, &size);
61   auth.data = malloc(size);
62   if (!auth.data)
63     goto out;
64   memcpy(auth.data, data, size);
65   free(data);
66   auth.length = size;
67
68   code = krb5_init_context(&context);
69   if (code)
70     {
71       com_err(whoami, code, "Initializing context");
72       send_int(conn, code);
73       goto out;
74     }
75
76   code = krb5_auth_con_init(context, &auth_con);
77   if (code)
78     {
79       com_err(whoami, code, "Initializing auth context");
80       send_int(conn, code);
81       goto out;
82     }
83
84   if (uname(&uts) < 0)
85     {
86       com_err(whoami, errno, "Unable to get local hostname");
87       send_int(conn, errno);
88       goto out;
89     }
90
91   code = krb5_sname_to_principal(context, uts.nodename, service,
92                                  KRB5_NT_SRV_HST, &server);
93
94   if (code)
95     {
96       com_err(whoami, code, "(krb5_sname_to_principal failed)");
97       send_int(conn, code);
98       goto out;
99     }
100
101   code = krb5_rd_req(context, &auth_con, &auth, server, NULL, NULL, &ticket);
102
103   if (code)
104     {
105       strcpy(name, qmark);
106       strcpy(inst, qmark);
107       strcpy(realm, qmark);
108       com_err(whoami, code, "auth for %s.%s@%s failed", name, inst, realm);
109       send_int(conn, code);
110       goto out;
111     }
112
113   code = krb5_copy_principal(context, ticket->enc_part2->client, &client);
114   if (code)
115     {
116       com_err(whoami, code, "(krb5_copy_principal failed)");
117       send_int(conn, code);
118       goto out;
119     }
120
121   code = krb5_524_conv_principal(context, client, name, inst, realm);
122   if (code)
123     {
124       com_err(whoami, code, "(krb5_524_conv_principal_failed)");
125       send_int(conn, code);
126       goto out;
127     }
128
129   /* If there is an auth record in the config file matching the
130    * authenticator we received, then accept it.  If there's no
131    * auth record, assume [master]@[local realm].
132    */
133   if ((first = p = config_lookup("auth")))
134     {
135       do
136         {
137           kname_parse(aname, ainst, arealm, p);
138           if (strcmp(aname, name) ||
139               strcmp(ainst, inst) ||
140               strcmp(arealm, realm))
141             p = config_lookup("auth");
142           else
143             p = first;
144         }
145       while (p != first);
146     }
147   else 
148     {
149       strcpy(aname, master);
150       strcpy(ainst, "");
151       if (!krb5_get_default_realm(context, &lrealm))
152         {
153           strcpy(arealm, lrealm);
154         }
155       else
156         strcpy(arealm, KRB_REALM);
157     }
158   code = EPERM;
159   if (strcmp(aname, name) ||
160       strcmp(ainst, inst) ||
161       strcmp(arealm, realm))
162     {
163       com_err(whoami, code, "auth for %s.%s@%s failed", name, inst, realm);
164       send_int(conn, code);
165       goto out;
166     }
167   send_ok(conn);
168   have_authorization = 1;
169
170  out:
171   if (lrealm)
172     free(lrealm);
173   if (client)
174     krb5_free_principal(context, client);
175   if (server)
176     krb5_free_principal(context, server);
177   if (ticket)
178     krb5_free_ticket(context, ticket);
179   krb5_free_data_contents(context, &auth);
180   if (auth_con)
181     krb5_auth_con_free(context, auth_con);
182   return;
183 }
This page took 0.061836 seconds and 5 git commands to generate.