xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/profile/prof_set.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
1 #pragma ident	"%Z%%M%	%I%	%E% SMI"
2 /*
3  * prof_set.c --- routines that expose the public interfaces for
4  * 	inserting, updating and deleting items from the profile.
5  *
6  * WARNING: These routines only look at the first file opened in the
7  * profile.  It's not clear how to handle multiple files, actually.
8  * In the future it may be necessary to modify this public interface,
9  * or possibly add higher level functions to support this correctly.
10  *
11  * WARNING: We're not yet doing locking yet, either.
12  *
13  */
14 
15 #include "prof_int.h"
16 
17 #include <stdio.h>
18 #include <string.h>
19 #ifdef HAVE_STDLIB_H
20 #include <stdlib.h>
21 #endif
22 #include <errno.h>
23 
24 static errcode_t rw_setup(profile_t profile)
25 {
26    	prf_file_t	file;
27 	errcode_t	retval = 0;
28 
29 	if (!profile)
30 		return PROF_NO_PROFILE;
31 
32 	if (profile->magic != PROF_MAGIC_PROFILE)
33 		return PROF_MAGIC_PROFILE;
34 
35 	file = profile->first_file;
36 
37 	retval = profile_lock_global();
38 	if (retval)
39 	    return retval;
40 
41 	/* Don't update the file if we've already made modifications */
42 	if (file->data->flags & PROFILE_FILE_DIRTY) {
43 	    profile_unlock_global();
44 	    return 0;
45 	}
46 
47 	if ((file->data->flags & PROFILE_FILE_SHARED) != 0) {
48 	    prf_data_t new_data;
49 	    new_data = profile_make_prf_data(file->data->filespec);
50 	    if (new_data == NULL) {
51 		retval = ENOMEM;
52 	    } else {
53 		retval = k5_mutex_init(&new_data->lock);
54 		if (retval == 0) {
55 		    new_data->root = NULL;
56 		    new_data->flags = file->data->flags & ~PROFILE_FILE_SHARED;
57 		    new_data->timestamp = 0;
58 		    new_data->upd_serial = file->data->upd_serial;
59 		}
60 	    }
61 
62 	    if (retval != 0) {
63 		profile_unlock_global();
64 		free(new_data);
65 		return retval;
66 	    }
67 	    profile_dereference_data_locked(file->data);
68 	    file->data = new_data;
69 	}
70 
71 	profile_unlock_global();
72 	retval = profile_update_file(file);
73 
74 	return retval;
75 }
76 
77 
78 /*
79  * Delete or update a particular child node
80  *
81  * ADL - 2/23/99, rewritten TYT 2/25/99
82  */
83 errcode_t KRB5_CALLCONV
84 profile_update_relation(profile_t profile, const char **names,
85 			const char *old_value, const char *new_value)
86 {
87 	errcode_t	retval;
88 	struct profile_node *section, *node;
89 	void		*state;
90 	const char	**cpp;
91 
92 	retval = rw_setup(profile);
93 	if (retval)
94 		return retval;
95 
96 	if (names == 0 || names[0] == 0 || names[1] == 0)
97 		return PROF_BAD_NAMESET;
98 
99 	if (!old_value || !*old_value)
100 		return PROF_EINVAL;
101 
102 	retval = k5_mutex_lock(&profile->first_file->data->lock);
103 	if (retval)
104 	    return retval;
105 	section = profile->first_file->data->root;
106 	for (cpp = names; cpp[1]; cpp++) {
107 		state = 0;
108 		retval = profile_find_node(section, *cpp, 0, 1,
109 					   &state, &section);
110 		if (retval) {
111 		    k5_mutex_unlock(&profile->first_file->data->lock);
112 		    return retval;
113 		}
114 	}
115 
116 	state = 0;
117 	retval = profile_find_node(section, *cpp, old_value, 0, &state, &node);
118 	if (retval == 0) {
119 	    if (new_value)
120 		retval = profile_set_relation_value(node, new_value);
121 	    else
122 		retval = profile_remove_node(node);
123 	}
124 	if (retval == 0)
125 	    profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
126 	k5_mutex_unlock(&profile->first_file->data->lock);
127 
128 	return retval;
129 }
130 
131 /*
132  * Clear a particular all of the relations with a specific name.
133  *
134  * TYT - 2/25/99
135  */
136 errcode_t KRB5_CALLCONV
137 profile_clear_relation(profile_t profile, const char **names)
138 {
139 	errcode_t	retval;
140 	struct profile_node *section, *node;
141 	void		*state;
142 	const char	**cpp;
143 
144 	retval = rw_setup(profile);
145 	if (retval)
146 		return retval;
147 
148 	if (names == 0 || names[0] == 0 || names[1] == 0)
149 		return PROF_BAD_NAMESET;
150 
151 	section = profile->first_file->data->root;
152 	for (cpp = names; cpp[1]; cpp++) {
153 		state = 0;
154 		retval = profile_find_node(section, *cpp, 0, 1,
155 					   &state, &section);
156 		if (retval)
157 			return retval;
158 	}
159 
160 	state = 0;
161 	do {
162 		retval = profile_find_node(section, *cpp, 0, 0, &state, &node);
163 		if (retval)
164 			return retval;
165 		retval = profile_remove_node(node);
166 		if (retval)
167 			return retval;
168 	} while (state);
169 
170 	profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
171 
172 	return 0;
173 }
174 
175 /*
176  * Rename a particular section; if the new_section name is NULL,
177  * delete it.
178  *
179  * ADL - 2/23/99, rewritten TYT 2/25/99
180  */
181 errcode_t KRB5_CALLCONV
182 profile_rename_section(profile_t profile, const char **names,
183 		       const char *new_name)
184 {
185 	errcode_t	retval;
186 	struct profile_node *section, *node;
187 	void		*state;
188 	const char	**cpp;
189 
190 	retval = rw_setup(profile);
191 	if (retval)
192 		return retval;
193 
194 	if (names == 0 || names[0] == 0 || names[1] == 0)
195 		return PROF_BAD_NAMESET;
196 
197 	retval = k5_mutex_lock(&profile->first_file->data->lock);
198 	if (retval)
199 	    return retval;
200 	section = profile->first_file->data->root;
201 	for (cpp = names; cpp[1]; cpp++) {
202 		state = 0;
203 		retval = profile_find_node(section, *cpp, 0, 1,
204 					   &state, &section);
205 		if (retval) {
206 		    k5_mutex_unlock(&profile->first_file->data->lock);
207 		    return retval;
208 		}
209 	}
210 
211 	state = 0;
212 	retval = profile_find_node(section, *cpp, 0, 1, &state, &node);
213 	if (retval == 0) {
214 	    if (new_name)
215 		retval = profile_rename_node(node, new_name);
216 	    else
217 		retval = profile_remove_node(node);
218 	}
219 	if (retval == 0)
220 	    profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
221 	k5_mutex_unlock(&profile->first_file->data->lock);
222 	return retval;
223 }
224 
225 /*
226  * Insert a new relation.  If the new_value argument is NULL, then
227  * create a new section instead.
228  *
229  * Note: if the intermediate sections do not exist, this function will
230  * automatically create them.
231  *
232  * ADL - 2/23/99, rewritten TYT 2/25/99
233  */
234 errcode_t KRB5_CALLCONV
235 profile_add_relation(profile_t profile, const char **names,
236 		     const char *new_value)
237 {
238 	errcode_t	retval;
239     	struct profile_node *section;
240 	const char 	**cpp;
241 	void		*state;
242 
243 	retval = rw_setup(profile);
244 	if (retval)
245 		return retval;
246 
247 	if (names == 0 || names[0] == 0 || names[1] == 0)
248 		return PROF_BAD_NAMESET;
249 
250 	retval = k5_mutex_lock(&profile->first_file->data->lock);
251 	if (retval)
252 	    return retval;
253 	section = profile->first_file->data->root;
254 	for (cpp = names; cpp[1]; cpp++) {
255 		state = 0;
256 		retval = profile_find_node(section, *cpp, 0, 1,
257 					   &state, &section);
258 		if (retval == PROF_NO_SECTION)
259 			retval = profile_add_node(section, *cpp, 0, &section);
260 		if (retval) {
261 		    k5_mutex_unlock(&profile->first_file->data->lock);
262 		    return retval;
263 		}
264 	}
265 
266 	if (new_value == 0) {
267 		retval = profile_find_node(section, *cpp, 0, 1, &state, 0);
268 		if (retval == 0) {
269 		    k5_mutex_unlock(&profile->first_file->data->lock);
270 		    return PROF_EXISTS;
271 		} else if (retval != PROF_NO_SECTION) {
272 		    k5_mutex_unlock(&profile->first_file->data->lock);
273 		    return retval;
274 		}
275 	}
276 
277 	retval = profile_add_node(section, *cpp, new_value, 0);
278 	if (retval) {
279 	    k5_mutex_unlock(&profile->first_file->data->lock);
280 	    return retval;
281 	}
282 
283 	profile->first_file->data->flags |= PROFILE_FILE_DIRTY;
284 	k5_mutex_unlock(&profile->first_file->data->lock);
285 	return 0;
286 }
287 
288