Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / platform / DARWIN / AklogAuthPlugin / aklog.c
CommitLineData
805e021f
CE
1/*
2 *
3 * aklog auth plugin, Taken from rot13 with guidance from NullAuthPlugin
4 * Copyright (c) 2010 Your File System Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <stdlib.h>
28#include <string.h>
29#include <syslog.h>
30#include <unistd.h>
31#include <sys/kauth.h>
32
33#include <Security/AuthorizationTags.h>
34#include <Security/AuthorizationPlugin.h>
35#include <DirectoryService/DirectoryService.h>
36
37typedef struct PluginRef
38{
39 const AuthorizationCallbacks *callbacks;
40} PluginRef;
41
42typedef struct MechanismRef
43{
44 const PluginRef *plugin;
45 AuthorizationEngineRef engine;
46 char *mechanismArg;
47} MechanismRef;
48
49static OSStatus do_aklog(char *cell)
50{
51 /*
52 * The first draft used aklog source inline. In an rxgk
53 * universe, that code should be encapsulated in a library
54 * we call. In this version we simply fork aklog.
55 * This function should be replaced with calls to a "libaklog"
56 */
57
58 char *aklogCmd;
59 if (cell) {
60 if (asprintf(&aklogCmd, "/usr/bin/aklog %s", cell) < 0)
61 aklogCmd = NULL;
62 if (aklogCmd)
63 return system(aklogCmd);
64 else
65 return -1;
66 }
67
68 return system("/usr/bin/aklog");
69}
70
71static OSStatus invokeAklog(MechanismRef *mechanism)
72{
73 AuthorizationContextFlags contextFlags;
74 const AuthorizationValue *value;
75 OSStatus status;
76 uid_t uid = 0;
77 gid_t gid = 0;
78
79 /* a list of context values appears in the Null sample plugin */
80 status = mechanism->plugin->callbacks->GetContextValue(mechanism->engine,
81 kDS1AttrUniqueID,
82 &contextFlags,
83 &value);
84
85 /* This and the group are strings. I don't know why. */
86 if (!status)
87 uid = atoi(value->data);
88 else
89 goto failed;
90
91 status = mechanism->plugin->callbacks->GetContextValue(mechanism->engine,
92 kDS1AttrPrimaryGroupID,
93 &contextFlags,
94 &value);
95 if (!status)
96 gid = atoi(value->data);
97 else
98 goto failed;
99
100 /* in a PAGless universe, this trick works */
101 status = pthread_setugid_np(uid, gid);
102 if (status == 0) {
103 status = do_aklog(mechanism->mechanismArg);
104 pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE);
105 if (status)
106 goto failed;
107 }
108
109 status =
110 mechanism->plugin->callbacks->SetResult(mechanism->engine,
111 kAuthorizationResultAllow);
112
113 if (!status)
114 return errAuthorizationSuccess;
115
116failed:
117 return errAuthorizationInternal;
118}
119
120static OSStatus pluginDestroy(AuthorizationPluginRef inPlugin)
121{
122 /* seems to not be called. can't do cleanup? */
123 PluginRef *plugin = (PluginRef *)inPlugin;
124 free(plugin);
125 return 0;
126}
127
128static OSStatus mechanismCreate(AuthorizationPluginRef inPlugin,
129 AuthorizationEngineRef inEngine,
130 AuthorizationMechanismId mechanismId,
131 AuthorizationMechanismRef *outMechanism)
132{
133 const PluginRef *plugin = (const PluginRef *)inPlugin;
134
135 MechanismRef *mechanism = calloc(1, sizeof(MechanismRef));
136
137 mechanism->plugin = plugin;
138 mechanism->engine = inEngine;
139 /*
140 * consider supporting a variant which backgrounds aklog and returns
141 * success where tokens are desired but not critical.
142 */
143 mechanism->mechanismArg = strdup(mechanismId);
144
145 *outMechanism = mechanism;
146
147 return 0;
148}
149
150
151static OSStatus mechanismInvoke(AuthorizationMechanismRef inMechanism)
152{
153 MechanismRef *mechanism = (MechanismRef *)inMechanism;
154 OSStatus status;
155
156 status = invokeAklog(mechanism);
157 if (status)
158 return errAuthorizationInternal;
159
160 /* mark success */
161 return mechanism->plugin->callbacks->SetResult(mechanism->engine, kAuthorizationResultAllow);
162}
163
164
165/**
166 * Since a authorization result is provided within invoke, we don't have to
167 * cancel a long(er) term operation that might have been spawned.
168 * A timeout could be done here.
169 */
170static OSStatus mechanismDeactivate(AuthorizationMechanismRef inMechanism)
171{
172 return 0;
173}
174
175
176static OSStatus mechanismDestroy(AuthorizationMechanismRef inMechanism)
177{
178 MechanismRef *mechanism = (MechanismRef *)inMechanism;
179 free(mechanism->mechanismArg);
180 free(mechanism);
181
182 return 0;
183}
184
185
186AuthorizationPluginInterface pluginInterface =
187{
188 kAuthorizationPluginInterfaceVersion, /* UInt32 version; */
189 pluginDestroy,
190 mechanismCreate,
191 mechanismInvoke,
192 mechanismDeactivate,
193 mechanismDestroy
194};
195
196
197/**
198 * Entry point for all plugins. Plugin and the host loading it exchange interfaces.
199 * Normally you'd allocate resources shared amongst all mechanisms here.
200 * When a plugin is created it may not necessarily be used, so be conservative
201 */
202OSStatus AuthorizationPluginCreate(const AuthorizationCallbacks *callbacks,
203 AuthorizationPluginRef *outPlugin,
204 const AuthorizationPluginInterface **outPluginInterface)
205{
206 PluginRef *plugin = calloc(1, sizeof(PluginRef));
207
208 plugin->callbacks = callbacks;
209 *outPlugin = (AuthorizationPluginRef) plugin;
210 *outPluginInterface = &pluginInterface;
211 return 0;
212}