1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/* $Id$
**
** Implementation of srvtab handling for the wallet client.
**
** Written by Russ Allbery <rra@stanford.edu>
** Copyright 2007 Board of Trustees, Leland Stanford Jr. University
**
** See LICENSE for licensing terms.
*/
#include <config.h>
#include <system.h>
#include <krb5.h>
#include <client/internal.h>
#include <util/util.h>
#ifndef KRB5_KRB4_COMPAT
# define ANAME_SZ 40
# define INST_SZ 40
# define REALM_SZ 40
#endif
#ifdef HAVE_KRB5_GET_ERROR_MESSAGE
static const char *
strerror_krb5(krb5_context ctx, krb5_error_code code)
{
const char *msg;
msg = krb5_get_error_message(ctx, code);
if (msg == NULL)
return "unknown error";
else
return msg;
}
#elif HAVE_KRB5_GET_ERR_TEXT
static const char *
strerror_krb5(krb5_context ctx, krb5_error_code code)
{
return krb5_get_err_text(ctx, code);
}
#else /* !HAVE_KRB5_GET_ERROR_MESSAGE */
static const char *
strerror_krb5(krb5_context ctx UNUSED, krb5_error_code code)
{
return error_message(code);
}
#endif
#ifdef HAVE_KRB5_FREE_ERROR_MESSAGE
static void
strerror_krb5_free(krb5_context ctx, const char *msg)
{
krb5_free_error_message(ctx, msg);
}
#else /* !HAVE_KRB5_FREE_ERROR_MESSAGE */
static void
strerror_krb5_free(krb5_context ctx UNUSED, const char *msg UNUSED)
{
return;
}
#endif /* !HAVE_KRB5_FREE_ERROR_MESSAGE */
/*
** Report a Kerberos error and exit.
*/
static void
die_krb5(krb5_context ctx, const char *message, krb5_error_code code)
{
const char *k5_msg = NULL;
k5_msg = strerror_krb5(ctx, code);
warn("%s: %s\n", message, k5_msg);
strerror_krb5_free(ctx, k5_msg);
exit(1);
}
/*
** Given the srvtab file name, a Kerberos principal (as a string), and a
** keytab file name, extract the des-cbc-crc key from that keytab and write
** it to the newly created srvtab file as a srvtab. Convert the principal
** from Kerberos v5 form to Kerberos v4 form.
**
** We always force the kvno to 0 for the srvtab. This works with how the
** wallet synchronizes keys, even though it's not particularly correct.
**
** On any failure, print an error message to standard error and then exit.
*/
void
write_srvtab(const char *srvtab, const char *principal, const char *keytab)
{
krb5_context ctx = NULL;
krb5_keytab kt;
krb5_principal princ;
krb5_keytab_entry entry;
krb5_error_code ret;
size_t length;
char aname[ANAME_SZ + 1] = "";
char inst[INST_SZ + 1] = "";
char realm[REALM_SZ + 1] = "";
char data[ANAME_SZ + 1 + INST_SZ + 1 + REALM_SZ + 1 + 1 + 8];
/* Open the keytab and get the DES key. */
ret = krb5_init_context(&ctx);
if (ret != 0)
die_krb5(ctx, "error creating Kerberos context", ret);
ret = krb5_parse_name(ctx, principal, &princ);
if (ret != 0)
die_krb5(ctx, "error parsing Kerberos principal", ret);
ret = krb5_kt_resolve(ctx, keytab, &kt);
if (ret != 0)
die_krb5(ctx, "error opening keytab", ret);
ret = krb5_kt_get_entry(ctx, kt, princ, 0, ENCTYPE_DES_CBC_CRC, &entry);
if (ret != 0)
die_krb5(ctx, "error reading DES key from keytab", ret);
if (entry.key.length != 8) {
fprintf(stderr, "invalid DES key length in keytab\n");
exit(1);
}
krb5_kt_close(ctx, kt);
/* Convert the principal to a Kerberos v4 principal. */
ret = krb5_524_conv_principal(ctx, princ, aname, inst, realm);
if (ret != 0)
die_krb5(ctx, "error converting principal to Kerberos v4", ret);
/* Assemble the srvtab data. */
length = 0;
strcpy(data + length, aname);
length += strlen(aname);
data[length++] = '\0';
strcpy(data + length, inst);
length += strlen(inst);
data[length++] = '\0';
strcpy(data + length, realm);
length += strlen(realm);
data[length++] = '\0';
data[length++] = '\0';
memcpy(data + length, entry.key.contents, 8);
length += 8;
krb5_free_keytab_entry_contents(ctx, &entry);
/* Write out the srvtab file. */
write_file(srvtab, data, length);
}
|