source: trunk/third/moira/update/auth_003.c @ 25817

Revision 25817, 4.7 KB checked in by jdreed, 12 years ago (diff)
In moira: * Re-snapshot moira at r4097 to pick up Status 10 (Suspended) (Trac: #1295) * Remove our addusr.1 and namespace.1 in favor of upstreams (Trac: #918) * Build-dep on OpenSSL and pass new configure flag per moira r4091
Line 
1/* $Id: auth_003.c 4092 2013-01-18 15:36:33Z zacheiss $
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
25RCSID("$HeadURL: svn+ssh://svn.mit.edu/moira/trunk/moira/update/auth_003.c $ $Id: auth_003.c 4092 2013-01-18 15:36:33Z zacheiss $");
26
27static char service[] = "host";
28static char master[] = "sms";
29static 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
41void 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, allowed = NULL;
47  krb5_ticket *ticket;
48  char *p, *first, *data, *pname = NULL, *mname = NULL, *lrealm = NULL;
49  char name[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ];
50  char aname[ANAME_SZ], ainst[INST_SZ], arealm[REALM_SZ];
51  size_t size;
52  long code;
53  struct utsname uts;
54
55  ticket = NULL;
56
57  send_ok(conn);
58
59  recv_string(conn, &data, &size);
60  auth.data = malloc(size);
61  if (!auth.data)
62    goto out;
63  memcpy(auth.data, data, size);
64  free(data);
65  auth.length = size;
66
67  code = krb5_init_context(&context);
68  if (code)
69    {
70      com_err(whoami, code, "Initializing context");
71      send_int(conn, code);
72      goto out;
73    }
74
75  code = krb5_auth_con_init(context, &auth_con);
76  if (code)
77    {
78      com_err(whoami, code, "Initializing auth context");
79      send_int(conn, code);
80      goto out;
81    }
82
83  if (uname(&uts) < 0)
84    {
85      com_err(whoami, errno, "Unable to get local hostname");
86      send_int(conn, errno);
87      goto out;
88    }
89
90  code = krb5_sname_to_principal(context, uts.nodename, service,
91                                 KRB5_NT_SRV_HST, &server);
92
93  if (code)
94    {
95      com_err(whoami, code, "(krb5_sname_to_principal failed)");
96      send_int(conn, code);
97      goto out;
98    }
99
100  code = krb5_rd_req(context, &auth_con, &auth, server, NULL, NULL, &ticket);
101
102  if (code)
103    {
104      strcpy(name, qmark);
105      strcpy(inst, qmark);
106      strcpy(realm, qmark);
107      com_err(whoami, code, "auth for %s.%s@%s failed", name, inst, realm);
108      send_int(conn, code);
109      goto out;
110    }
111
112  code = krb5_copy_principal(context, ticket->enc_part2->client, &client);
113  if (code)
114    {
115      com_err(whoami, code, "(krb5_copy_principal failed)");
116      send_int(conn, code);
117      goto out;
118    }
119
120  /* If there is an auth record in the config file matching the
121   * authenticator we received, then accept it.  If there's no
122   * auth record, assume [master]@[local realm].
123   */
124  if ((first = p = config_lookup("auth")))
125    {
126      do
127        {
128          code = krb5_parse_name(context, p, &allowed);
129          if (code)
130            {
131              com_err(whoami, code, "(krb5_parse_name failed)");
132              send_int(conn, code);
133              goto out;
134            }
135          if (!krb5_principal_compare(context, client, allowed))
136            {
137              krb5_free_principal(context, allowed);
138              p = config_lookup("auth");
139            }
140          else
141            p = first;
142        }
143      while (p != first);
144    }
145  else
146    {
147      mname = malloc(strlen(master) + 1);
148      if (!mname)
149        goto out;
150
151      strcpy(mname, master);
152
153      if (!krb5_get_default_realm(context, &lrealm))
154        {
155          mname = realloc(mname, strlen(master) + strlen(lrealm) + 2);
156          if (!mname)
157            goto out;
158          strncat(mname, "@", 1);
159          strncat(mname, lrealm, strlen(lrealm));
160        }
161      else
162        {
163          mname = realloc(mname, strlen(master) + strlen(KRB_REALM) + 2);
164          if (!mname)
165            goto out;
166          strncat(mname, "@", 1);
167          strncat(mname, KRB_REALM, strlen(KRB_REALM));
168        }
169
170      code = krb5_parse_name(context, mname, &allowed);
171      free(mname);
172
173      if (code)
174        {
175          com_err(whoami, code, "(krb5_parse_name failed)");
176          send_int(conn, code);
177          goto out;
178        }
179    }
180
181  code = EPERM;
182  if (!krb5_principal_compare(context, client, allowed))
183    {
184      krb5_unparse_name(context, client, &pname);
185      com_err(whoami, code, "auth for %s failed", pname);
186      send_int(conn, code);
187      goto out;
188    }
189  send_ok(conn);
190  have_authorization = 1;
191 
192 out:
193  if (pname)
194    krb5_free_unparsed_name(context, pname);
195  if (lrealm)
196    free(lrealm);
197  if (allowed)
198    krb5_free_principal(context, allowed);
199  if (client)
200    krb5_free_principal(context, client);
201  if (server)
202    krb5_free_principal(context, server);
203  if (ticket)
204    krb5_free_ticket(context, ticket);
205  krb5_free_data_contents(context, &auth);
206  if (auth_con)
207    krb5_auth_con_free(context, auth_con);
208  return;
209}
Note: See TracBrowser for help on using the repository browser.