60be9e85d5d3284eb50eb42a79d37004dc0259bd
[platform/upstream/krb5.git] / src / lib / kadm5 / unit-test / setkey-test.c
1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 #include <k5-int.h>
3 #include <kadm5/admin.h>
4
5 #if     HAVE_SRAND48
6 #define RAND()          lrand48()
7 #define SRAND(a)        srand48(a)
8 #define RAND_TYPE       long
9 #elif   HAVE_SRAND
10 #define RAND()          rand()
11 #define SRAND(a)        srand(a)
12 #define RAND_TYPE       int
13 #elif   HAVE_SRANDOM
14 #define RAND()          random()
15 #define SRAND(a)        srandom(a)
16 #define RAND_TYPE       long
17 #else   /* no random */
18 need a random number generator
19 #endif  /* no random */
20
21 krb5_keyblock test1[] = {
22     {0, ENCTYPE_DES_CBC_CRC, 0, 0},
23     {-1},
24 };
25 krb5_keyblock test2[] = {
26     {0, ENCTYPE_DES_CBC_CRC, 0, 0},
27     {-1},
28 };
29 krb5_keyblock test3[] = {
30     {0, ENCTYPE_DES_CBC_CRC, 0, 0},
31     {-1},
32 };
33
34 krb5_keyblock *tests[] = {
35     test1, test2, test3, NULL
36 };
37
38 #if 0
39 int keyblocks_equal(krb5_keyblock *kb1, krb5_keyblock *kb2)
40 {
41     return (kb1->enctype == kb2->enctype &&
42             kb1->length == kb2->length &&
43             memcmp(kb1->contents, kb2->contents, kb1->length) == 0);
44 }
45 #endif
46
47 krb5_data tgtname = {
48     0,
49     KRB5_TGS_NAME_SIZE,
50     KRB5_TGS_NAME
51 };
52
53 krb5_enctype ktypes[] = { 0, 0 };
54
55 extern krb5_kt_ops krb5_ktf_writable_ops;
56
57 int
58 main(int argc, char **argv)
59 {
60     krb5_context context;
61     krb5_keytab kt;
62     krb5_keytab_entry ktent;
63     krb5_encrypt_block eblock;
64     krb5_creds my_creds;
65     krb5_get_init_creds_opt *opt;
66     kadm5_principal_ent_rec princ_ent;
67     krb5_principal princ, server;
68     char pw[16];
69     char *whoami, *principal, *authprinc, *authpwd;
70     krb5_data pwdata;
71     void *handle;
72     int ret, i, test, encnum;
73
74     whoami = argv[0];
75
76     if (argc < 2 || argc > 4) {
77         fprintf(stderr, "Usage: %s principal [authuser] [authpwd]\n", whoami);
78         exit(1);
79     }
80     principal = argv[1];
81     authprinc = (argc > 2) ? argv[2] : argv[0];
82     authpwd = (argc > 3) ? argv[3] : NULL;
83
84     /*
85      * Setup.  Initialize data structures, open keytab, open connection
86      * to kadm5 server.
87      */
88
89     memset(&context, 0, sizeof(context));
90     kadm5_init_krb5_context(&context);
91
92     ret = krb5_parse_name(context, principal, &princ);
93     if (ret) {
94         com_err(whoami, ret, "while parsing principal name %s", principal);
95         exit(1);
96     }
97
98     if((ret = krb5_build_principal_ext(context, &server,
99                                        krb5_princ_realm(kcontext, princ)->length,
100                                        krb5_princ_realm(kcontext, princ)->data,
101                                        tgtname.length, tgtname.data,
102                                        krb5_princ_realm(kcontext, princ)->length,
103                                        krb5_princ_realm(kcontext, princ)->data,
104                                        0))) {
105         com_err(whoami, ret, "while building server name");
106         exit(1);
107     }
108
109     ret = krb5_kt_default(context, &kt);
110     if (ret) {
111         com_err(whoami, ret, "while opening keytab");
112         exit(1);
113     }
114
115     ret = kadm5_init(context, authprinc, authpwd, KADM5_ADMIN_SERVICE, NULL,
116                      KADM5_STRUCT_VERSION, KADM5_API_VERSION_4, NULL,
117                      &handle);
118     if (ret) {
119         com_err(whoami, ret, "while initializing connection");
120         exit(1);
121     }
122
123     /* these pw's don't need to be secure, just different every time */
124     SRAND((RAND_TYPE)time((void *) NULL));
125     pwdata.data = pw;
126     pwdata.length = sizeof(pw);
127
128     /*
129      * For each test:
130      *
131      * For each enctype in the test, construct a random password/key.
132      * Assign all keys to principal with kadm5_setkey_principal.  Add
133      * each key to the keytab, and acquire an initial ticket with the
134      * keytab (XXX can I specify the kvno explicitly?).  If
135      * krb5_get_init_creds_keytab succeeds, then the keys were set
136      * successfully.
137      */
138     for (test = 0; tests[test] != NULL; test++) {
139         krb5_keyblock *testp = tests[test];
140         kadm5_key_data *extracted;
141         int n_extracted, match;
142         printf("+ Test %d:\n", test);
143
144         for (encnum = 0; testp[encnum].magic != -1; encnum++) {
145             for (i = 0; i < sizeof(pw); i++)
146                 pw[i] = (RAND() % 26) + '0'; /* XXX */
147
148             krb5_use_enctype(context, &eblock, testp[encnum].enctype);
149             ret = krb5_string_to_key(context, &eblock, &testp[encnum],
150                                      &pwdata, NULL);
151             if (ret) {
152                 com_err(whoami, ret, "while converting string to key");
153                 exit(1);
154             }
155         }
156
157         /* now, encnum == # of keyblocks in testp */
158         ret = kadm5_setkey_principal(handle, princ, testp, encnum);
159         if (ret) {
160             com_err(whoami, ret, "while setting keys");
161             exit(1);
162         }
163
164         ret = kadm5_get_principal(handle, princ, &princ_ent, KADM5_KVNO);
165         if (ret) {
166             com_err(whoami, ret, "while retrieving principal");
167             exit(1);
168         }
169
170         ret = kadm5_get_principal_keys(handle, princ, 0, &extracted,
171                                        &n_extracted);
172         if (ret) {
173             com_err(whoami, ret, "while extracting keys");
174             exit(1);
175         }
176
177         for (encnum = 0; testp[encnum].magic != -1; encnum++) {
178             printf("+   enctype %d\n", testp[encnum].enctype);
179
180             for (match = 0; match < n_extracted; match++) {
181                 if (extracted[match].key.enctype == testp[encnum].enctype)
182                     break;
183             }
184             if (match >= n_extracted) {
185                 com_err(whoami, KRB5_WRONG_ETYPE, "while matching enctypes");
186                 exit(1);
187             }
188             if (extracted[match].key.length != testp[encnum].length ||
189                 memcmp(extracted[match].key.contents, testp[encnum].contents,
190                        testp[encnum].length) != 0) {
191                 com_err(whoami, KRB5_KDB_NO_MATCHING_KEY, "verifying keys");
192                 exit(1);
193             }
194
195             memset(&ktent, 0, sizeof(ktent));
196             ktent.principal = princ;
197             ktent.key = testp[encnum];
198             ktent.vno = princ_ent.kvno;
199
200             ret = krb5_kt_add_entry(context, kt, &ktent);
201             if (ret) {
202                 com_err(whoami, ret, "while adding keytab entry");
203                 exit(1);
204             }
205
206             memset(&my_creds, 0, sizeof(my_creds));
207             my_creds.client = princ;
208             my_creds.server = server;
209
210             ktypes[0] = testp[encnum].enctype;
211             ret = krb5_get_init_creds_opt_alloc(context, &opt);
212             if (ret) {
213                 com_err(whoami, ret, "while allocating gic opts");
214                 exit(1);
215             }
216             krb5_get_init_creds_opt_set_etype_list(opt, ktypes, 1);
217             ret = krb5_get_init_creds_keytab(context, &my_creds, princ,
218                                              kt, 0, NULL /* in_tkt_service */,
219                                              opt);
220             krb5_get_init_creds_opt_free(context, opt);
221             if (ret) {
222                 com_err(whoami, ret, "while acquiring initial ticket");
223                 exit(1);
224             }
225             krb5_free_cred_contents(context, &my_creds);
226
227             /* since I can't specify enctype explicitly ... */
228             ret = krb5_kt_remove_entry(context, kt, &ktent);
229             if (ret) {
230                 com_err(whoami, ret, "while removing keytab entry");
231                 exit(1);
232             }
233         }
234
235         (void)kadm5_free_kadm5_key_data(context, n_extracted, extracted);
236     }
237
238     ret = krb5_kt_close(context, kt);
239     if (ret) {
240         com_err(whoami, ret, "while closing keytab");
241         exit(1);
242     }
243
244     ret = kadm5_destroy(handle);
245     if (ret) {
246         com_err(whoami, ret, "while closing kadmin connection");
247         exit(1);
248     }
249
250     krb5_free_principal(context, princ);
251     krb5_free_principal(context, server);
252     krb5_free_context(context);
253     return 0;
254 }