1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#pragma ident	"%Z%%M%	%I%	%E% SMI"
27
28/*LINTLIBRARY*/
29
30#include <stdlib.h>
31#include <stdio.h>
32#include <stdarg.h>
33#include <string.h>
34#include <alloca.h>
35#include <libintl.h>
36#include <papi_impl.h>
37
38#include <tsol/label.h>
39
40papi_status_t
41papiServiceCreate(papi_service_t *handle, char *service_name,
42		char *user_name, char *password,
43		int (*authCB)(papi_service_t svc, void *app_data),
44		papi_encryption_t encryption, void *app_data)
45{
46	service_t *svc = NULL;
47	char *path = Lp_FIFO;
48
49	if (handle == NULL)
50		return (PAPI_BAD_ARGUMENT);
51
52	if ((*handle = svc = calloc(1, sizeof (*svc))) == NULL)
53		return (PAPI_TEMPORARY_ERROR);
54
55	svc->md = mconnect(path, 0, 0);
56	if (svc->md == NULL) {
57		detailed_error(svc,
58			gettext("can't connect to spooler for %s: %s"),
59			(service_name ? service_name : ""), strerror(errno));
60		return (PAPI_SERVICE_UNAVAILABLE);
61	}
62
63	svc->msgbuf_size = MSGMAX;
64	if ((svc->msgbuf = calloc(1, svc->msgbuf_size)) == NULL)
65		return (PAPI_TEMPORARY_ERROR);
66
67	if (service_name != NULL)
68		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_EXCL,
69				"service-name", service_name);
70
71	(void) papiServiceSetUserName(svc, user_name);
72	(void) papiServiceSetPassword(svc, password);
73	(void) papiServiceSetAuthCB(svc, authCB);
74	(void) papiServiceSetAppData(svc, app_data);
75	(void) papiServiceSetEncryption(svc, encryption);
76
77	return (PAPI_OK);
78}
79
80void
81papiServiceDestroy(papi_service_t handle)
82{
83	service_t *svc = handle;
84
85	if (svc != NULL) {
86		if (svc->md != NULL)
87			mdisconnect(svc->md);
88		if (svc->msgbuf != NULL)
89			free(svc->msgbuf);
90		papiAttributeListFree(svc->attributes);
91		free(svc);
92	}
93}
94
95/*
96 * interface for passing a peer's connection to gather sensitivity labeling
97 * from for Trusted Solaris.
98 */
99papi_status_t
100papiServiceSetPeer(papi_service_t handle, int peerfd)
101{
102	papi_status_t result = PAPI_OK;
103	service_t *svc = handle;
104
105	if (svc == NULL)
106		return (PAPI_BAD_ARGUMENT);
107
108	if (is_system_labeled()) {
109		short status;
110
111		if ((snd_msg(svc, S_PASS_PEER_CONNECTION) < 0) ||
112		    (ioctl(svc->md->writefd, I_SENDFD, peerfd) < 0) ||
113		    (rcv_msg(svc, R_PASS_PEER_CONNECTION, &status) < 0))
114			status = MTRANSMITERR;
115
116		if (status != MOK) {
117			detailed_error(svc,
118				gettext("failed to send peer connection: %s"),
119				lpsched_status_string(status));
120			result = lpsched_status_to_papi_status(status);
121		}
122	}
123
124	return (result);
125}
126
127papi_status_t
128papiServiceSetUserName(papi_service_t handle, char *user_name)
129{
130	service_t *svc = handle;
131
132	if (svc == NULL)
133		return (PAPI_BAD_ARGUMENT);
134
135	return (papiAttributeListAddString(&svc->attributes, PAPI_ATTR_REPLACE,
136				"user-name", user_name));
137}
138
139papi_status_t
140papiServiceSetPassword(papi_service_t handle, char *password)
141{
142	service_t *svc = handle;
143
144	if (svc == NULL)
145		return (PAPI_BAD_ARGUMENT);
146
147	return (papiAttributeListAddString(&svc->attributes, PAPI_ATTR_REPLACE,
148				"password", password));
149}
150
151papi_status_t
152papiServiceSetEncryption(papi_service_t handle,
153			papi_encryption_t encryption)
154{
155	service_t *svc = handle;
156
157	if (svc == NULL)
158		return (PAPI_BAD_ARGUMENT);
159
160	return (papiAttributeListAddInteger(&svc->attributes, PAPI_ATTR_REPLACE,
161				"encryption", (int)encryption));
162}
163
164papi_status_t
165papiServiceSetAuthCB(papi_service_t handle,
166			int (*authCB)(papi_service_t svc, void *app_data))
167{
168	service_t *svc = handle;
169
170	if (svc == NULL)
171		return (PAPI_BAD_ARGUMENT);
172
173	svc->authCB = (int (*)(papi_service_t svc, void *app_data))authCB;
174
175	return (PAPI_OK);
176}
177
178papi_status_t
179papiServiceSetAppData(papi_service_t handle, void *app_data)
180{
181	service_t *svc = handle;
182
183	if (svc == NULL)
184		return (PAPI_BAD_ARGUMENT);
185
186	svc->app_data = (void *)app_data;
187
188	return (PAPI_OK);
189}
190
191char *
192papiServiceGetServiceName(papi_service_t handle)
193{
194	service_t *svc = handle;
195	char *result = NULL;
196
197	if (svc != NULL)
198		papiAttributeListGetString(svc->attributes, NULL,
199					"service-name", &result);
200
201	return (result);
202}
203
204char *
205papiServiceGetUserName(papi_service_t handle)
206{
207	service_t *svc = handle;
208	char *result = NULL;
209
210	if (svc != NULL)
211		papiAttributeListGetString(svc->attributes, NULL,
212					"user-name", &result);
213
214	return (result);
215}
216
217char *
218papiServiceGetPassword(papi_service_t handle)
219{
220	service_t *svc = handle;
221	char *result = NULL;
222
223	if (svc != NULL)
224		papiAttributeListGetString(svc->attributes, NULL,
225					"password", &result);
226
227	return (result);
228}
229
230papi_encryption_t
231papiServiceGetEncryption(papi_service_t handle)
232{
233	service_t *svc = handle;
234	papi_encryption_t result = PAPI_ENCRYPT_NEVER;
235
236	if (svc != NULL)
237		papiAttributeListGetInteger(svc->attributes, NULL,
238					"encryption", (int *)&result);
239
240	return (result);
241}
242
243void *
244papiServiceGetAppData(papi_service_t handle)
245{
246	service_t *svc = handle;
247	void *result = NULL;
248
249	if (svc != NULL)
250		result = svc->app_data;
251
252	return (result);
253}
254
255papi_attribute_t **
256papiServiceGetAttributeList(papi_service_t handle)
257{
258	service_t *svc = handle;
259	papi_attribute_t **result = NULL;
260
261	if (svc != NULL) {
262		lpsched_service_information(&svc->attributes);
263		result = svc->attributes;
264	}
265
266	return (result);
267}
268
269char *
270papiServiceGetStatusMessage(papi_service_t handle)
271{
272	service_t *svc = handle;
273	char *result = NULL;
274
275	if (svc != NULL)
276		papiAttributeListGetString(svc->attributes, NULL,
277					"detailed-status-message", &result);
278
279	return (result);
280}
281
282void
283detailed_error(service_t *svc, char *fmt, ...)
284{
285	if ((svc != NULL) && (fmt != NULL)) {
286		va_list ap;
287		size_t size;
288		char *message = alloca(BUFSIZ);
289
290		va_start(ap, fmt);
291		/*
292		 * fill in the message.  If the buffer is too small, allocate
293		 * one that is large enough and fill it in.
294		 */
295		if ((size = vsnprintf(message, BUFSIZ, fmt, ap)) >= BUFSIZ)
296			if ((message = alloca(size)) != NULL)
297				vsnprintf(message, size, fmt, ap);
298		va_end(ap);
299
300		papiAttributeListAddString(&svc->attributes, PAPI_ATTR_APPEND,
301					"detailed-status-message", message);
302	}
303}
304