1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24#import <KerberosHelper/NetworkAuthenticationHelper.h>
25#import <KerberosHelper/NetworkAuthenticationHelperGSS.h>
26#import <KerberosHelper/KerberosHelper.h>
27#import <Foundation/Foundation.h>
28#import <GSS/gssapi.h>
29
30#include <unistd.h>
31#include <err.h>
32
33
34/* XXX application protocol code here
35 sample code only using GSS-API directly
36 */
37
38static void
39tryGSSAPI(gss_OID mech, gss_cred_id_t cred, gss_name_t servername, CFTypeRef name)
40{
41    OM_uint32 maj, junk;
42
43    gss_buffer_desc buffer;
44    gss_ctx_id_t ctx = NULL;
45
46    maj = gss_init_sec_context(&junk, cred, &ctx, servername, mech, 0, GSS_C_INDEFINITE, NULL, NULL,
47			       NULL, &buffer, NULL, NULL);
48    if (maj)
49	NSLog(@"ISC failed with %d/%d for %@", maj, junk, name);
50    else {
51	printf("ISC success, got first token\n");
52	gss_delete_sec_context(&junk, &ctx, NULL);
53	gss_release_buffer(&junk, &buffer);
54    }
55    gss_release_cred(&junk, &cred);
56    gss_release_name(&junk, &servername);
57}
58
59
60static int
61doit(CFStringRef username, CFStringRef password,
62     CFStringRef hostname, CFStringRef protocol)
63{
64    CFMutableDictionaryRef info = NULL;
65    CFDictionaryRef krbtoken = NULL;
66
67    if (protocol == NULL)
68	protocol = CFSTR("host");
69
70    info = CFDictionaryCreateMutable(NULL, 0,
71				     &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
72
73
74    krbtoken = KRBCreateNegTokenLegacyKerberos(NULL);
75    CFDictionaryAddValue(info, kNAHNegTokenInit, krbtoken);
76    CFRelease(krbtoken);
77
78    if (username)
79	CFDictionaryAddValue(info, kNAHUserName, username);
80
81    if (password)
82	CFDictionaryAddValue(info, kNAHPassword, password);
83
84
85    NAHRef nah = NAHCreate(NULL, hostname, protocol, info);
86    if (nah == NULL)
87	errx(1, "NAHCreate");
88
89    CFArrayRef selections = NAHGetSelections(nah);
90    if (selections == NULL)
91	errx(1, "NAHGetSelections");
92
93    CFIndex idx, count = CFArrayGetCount(selections);
94
95    printf("num selection: %ld\n", count);
96
97    for (idx = 0; idx < count; idx++) {
98	NAHSelectionRef sel =
99	    (NAHSelectionRef)CFArrayGetValueAtIndex(selections, idx);
100	CFErrorRef error;
101
102	CFStringRef clientPrincipal = NAHSelectionGetInfoForKey(sel, kNAHClientPrincipal);
103	CFStringRef serverPrincipal = NAHSelectionGetInfoForKey(sel, kNAHServerPrincipal);
104
105	NSLog(@"trying to get credential: client: %@ server: %@",
106	      (NSString *)clientPrincipal, (NSString *)serverPrincipal);
107
108	if (!NAHSelectionAcquireCredential(sel, NULL, &error)) {
109	    NSLog(@"failed to acquire cred: %@", error);
110	    if (error)
111		CFRelease(error);
112	    continue;
113	}
114
115	{
116	    gss_name_t servername = NAHSelectionGetGSSAcceptorName(sel, NULL);
117	    if (servername == NULL)
118		errx(1, "failed to get server name");
119
120	    gss_cred_id_t cred = NAHSelectionGetGSSCredential(sel, NULL);
121	    if (cred == NULL)
122		errx(1, "failed to get client credential");
123
124	    gss_OID mech = NAHSelectionGetGSSMech(sel);
125	    if (mech == NULL)
126		errx(1, "failed to get mech oid");
127
128
129	    tryGSSAPI(mech, cred, servername, sel);
130	}
131
132	{
133	    CFDictionaryRef authInfo = NAHSelectionCopyAuthInfo(sel);
134
135	    gss_cred_id_t cred = NAHAuthenticationInfoCopyClientCredential(authInfo, NULL);
136	    gss_name_t servername = NAHAuthenticationInfoCopyServerName(authInfo, NULL);
137	    gss_OID mech = NAHAuthenticationInfoGetGSSMechanism(authInfo, NULL);
138
139	    tryGSSAPI(mech, cred, servername, @"mech");
140	}
141
142    }
143
144
145    if (selections)
146	CFRelease(selections);
147    if (nah)
148	CFRelease(nah);
149
150    return 0;
151}
152
153static void
154usage(int exit_code)
155{
156    printf("%s [-u user] [-p password] [-s service] hostname1...\n", getprogname());
157    exit(exit_code);
158}
159
160int
161main(int argc, char **argv)
162{
163    CFStringRef username = NULL, password = NULL;
164    CFStringRef hostname = NULL, service = NULL;
165    int ch, i;
166
167    while ((ch = getopt(argc, argv, "u:p:s:")) != -1) {
168	switch (ch) {
169	case 'u':
170	    username = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
171	    break;
172	case 'p':
173	    password = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
174	    break;
175	case 's':
176	    service = CFStringCreateWithCString(NULL, optarg, kCFStringEncodingUTF8);
177	    break;
178	case '?':
179	    usage(0);
180	    break;
181	default:
182	    usage(1);
183	    break;
184	}
185    }
186    argc -= optind;
187    argv += optind;
188
189    if (argc < 0)
190	usage(1);
191
192    for (i = 0; i < argc; i++) {
193	hostname = CFStringCreateWithCString(NULL, argv[i], kCFStringEncodingUTF8);
194
195	doit(username, password, hostname, service);
196
197	CFRelease(hostname);
198    }
199
200    return 0;
201}
202