s4:torture: Adapt KDC canon test to Heimdal upstream changes
[samba.git] / source4 / heimdal / lib / gssapi / test_add_store_cred.c
1 /*
2  * Copyright (c) 2015 Cryptonector LLC.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. The name Cryptonector LLC may not be used to endorse or promote
17  *    products derived from this software without specific prior written
18  *    permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY
21  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
27  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
30  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <roken.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdarg.h>
42 #include <gssapi.h>
43 #include <err.h>
44 #include <getarg.h>
45
46 static void
47 print_gss_err(OM_uint32 stat, int status_type, gss_OID mech)
48 {
49     gss_buffer_desc str;
50     OM_uint32 maj;
51     OM_uint32 min;
52     OM_uint32 msg_ctx = 0;
53     int first = 1;
54
55     do {
56         maj = gss_display_status(&min, stat, status_type, mech, &msg_ctx,
57                                  &str);
58         if (maj != GSS_S_COMPLETE) {
59             fprintf(stderr, "Error displaying GSS %s error (%lu): %lu, %lu",
60                     status_type == GSS_C_GSS_CODE ? "major" : "minor",
61                     (unsigned long)stat, (unsigned long)maj,
62                     (unsigned long)min);
63             return;
64         }
65         if (first) {
66             fprintf(stderr, "GSS %s error: %.*s\n",
67                     status_type == GSS_C_GSS_CODE ? "major" : "minor",
68                     (int)str.length, (char *)str.value);
69             first = 0;
70         } else {
71             fprintf(stderr, "\t%.*s\n", (int)str.length, (char *)str.value);
72         }
73         gss_release_buffer(&min, &str);
74     } while (msg_ctx != 0);
75 }
76
77 static void
78 print_gss_errs(OM_uint32 major, OM_uint32 minor, gss_OID mech)
79 {
80     print_gss_err(major, GSS_C_GSS_CODE, GSS_C_NO_OID);
81     print_gss_err(major, GSS_C_MECH_CODE, mech);
82 }
83
84 static void
85 gss_err(int exitval, OM_uint32 major, OM_uint32 minor, gss_OID mech,
86         const char *fmt, ...)
87 {
88     va_list args;
89
90     va_start(args, fmt);
91     vwarnx(fmt, args);
92     va_end(args);
93     print_gss_errs(major, minor, mech);
94     exit(exitval);
95 }
96
97 static int version_flag         = 0;
98 static int help_flag            = 0;
99 static int env_flag             = 0;
100 static int def_flag             = 0;
101 static int overwrite_flag       = 0;
102
103 static struct getargs args[] = {
104     {"version", 0,      arg_flag,       &version_flag, "print version", NULL },
105     {"help",    0,      arg_flag,       &help_flag,  NULL, NULL },
106     {"env",     'e',    arg_flag,       &env_flag,
107      "output env settings", NULL },
108     {"default", 0,      arg_flag,       &def_flag,
109      "switch credential store default principal", NULL },
110     {"overwrite", 0,    arg_flag,       &overwrite_flag,
111      "overwrite matching credential", NULL },
112 };
113
114 static void
115 usage(int ret)
116 {
117     arg_printusage(args, sizeof(args)/sizeof(*args),
118                    NULL, "from_ccache to_ccache");
119     exit(ret);
120 }
121
122 int
123 main(int argc, char **argv)
124 {
125     OM_uint32 major, minor;
126     gss_cred_id_t from_cred = GSS_C_NO_CREDENTIAL;
127     gss_cred_id_t to_cred = GSS_C_NO_CREDENTIAL;
128     gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
129     gss_key_value_element_desc from_elements, to_elements;
130     gss_key_value_set_desc from, to;
131     gss_buffer_set_t env = GSS_C_NO_BUFFER_SET;
132     OM_uint32 store_flags = 0;
133     int optidx = 0;
134
135     setprogname(argv[0]);
136     if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
137         usage(1);
138
139     if (help_flag)
140         usage (0);
141
142     if (version_flag){
143         print_version(NULL);
144         exit(0);
145     }
146
147     if (def_flag)
148         store_flags |= GSS_C_STORE_CRED_DEFAULT;
149     if (overwrite_flag)
150         store_flags |= GSS_C_STORE_CRED_OVERWRITE;
151
152     argc -= optidx;
153     argv += optidx;
154
155     if (argc < 2)
156         errx(1, "required arguments missing");
157     if (argc > 2)
158         errx(1, "too many arguments");
159
160     from_elements.key = "ccache";
161     from_elements.value = argv[0];
162     from.count = 1;
163     from.elements = &from_elements;
164
165     to_elements.key = "ccache";
166     to_elements.value = argv[1];
167     to.count = 1;
168     to.elements = &to_elements;
169
170     major = gss_add_cred_from(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,
171                               GSS_KRB5_MECHANISM, GSS_C_INITIATE,
172                               GSS_C_INDEFINITE, GSS_C_INDEFINITE,
173                               &from, &from_cred, NULL, NULL, NULL);
174     if (major != GSS_S_COMPLETE)
175         gss_err(1, major, minor, GSS_KRB5_MECHANISM,
176                 "failed to acquire creds from %s", argv[0]);
177
178     major = gss_store_cred_into2(&minor, from_cred, GSS_C_INITIATE,
179                                  GSS_KRB5_MECHANISM, store_flags, &to, NULL,
180                                  NULL, env_flag ? &env : NULL);
181     if (major != GSS_S_COMPLETE)
182         gss_err(1, major, minor, GSS_KRB5_MECHANISM,
183                 "failed to store creds into %s", argv[1]);
184
185     if (env_flag) {
186         size_t i;
187         int got_krb5ccname = 0;
188
189         if (env == GSS_C_NO_BUFFER_SET)
190             warnx("No environment settings");
191
192         for (i = 0; env != GSS_C_NO_BUFFER_SET && i < env->count; i++) {
193             got_krb5ccname = got_krb5ccname ||
194                 (env->elements[i].length > sizeof("KRB5CCNAME=") &&
195                  strncmp((const char *)env->elements[i].value, "KRB5CCNAME=",
196                          sizeof("KRB5CCNAME=") - 1) == 0);
197             printf("%.*s\n", (int)env->elements[i].length,
198                    (const char *)env->elements[i].value);
199         }
200         (void) gss_release_buffer_set(&minor, &env);
201
202         if (!got_krb5ccname)
203             errx(1, "KRB5CCNAME environment variable not set by "
204                  "gss_store_cred_into2()");
205     }
206
207     (void) gss_release_cred(&minor, &from_cred);
208     (void) gss_release_cred(&minor, &to_cred);
209
210     major = gss_add_cred(&minor, GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME,
211                          GSS_KRB5_MECHANISM, GSS_C_INITIATE, GSS_C_INDEFINITE,
212                          GSS_C_INDEFINITE, &cred, NULL, NULL, NULL);
213     if (major != GSS_S_COMPLETE)
214         gss_err(1, major, minor, GSS_KRB5_MECHANISM,
215                 "failed to acquire creds from %s", argv[1]);
216     (void) gss_release_cred(&minor, &cred);
217
218     return 0;
219 }