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 2009 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26/*
27 * This is an extract from usr/src/common/smbsrv/smb_sid.c,
28 * with functions renamed as part of a tentative plan for convergence.
29 */
30#ifndef _KERNEL
31#include <stdio.h>
32#include <strings.h>
33#include <stdlib.h>
34#include <syslog.h>
35#else /* _KERNEL */
36#include <sys/types.h>
37#include <sys/sunddi.h>
38#endif /* _KERNEL */
39
40#include <sidutil.h>
41
42/*
43 * sid_len
44 *
45 * Returns the number of bytes required to hold the sid.
46 */
47int
48sid_len(sid_t *sid)
49{
50	if (sid == NULL)
51		return (0);
52
53	return (sizeof (sid_t) - sizeof (uint32_t)
54	    + (sid->sid_subauthcnt * sizeof (uint32_t)));
55}
56
57/*
58 * sid_tostr
59 *
60 * Fill in the passed buffer with the string form of the given
61 * binary sid.
62 */
63void
64sid_tostr(sid_t *sid, char *strsid)
65{
66	char *p = strsid;
67	int i;
68
69	if (sid == NULL || strsid == NULL)
70		return;
71
72	(void) sprintf(p, "S-%d-", sid->sid_revision);
73	while (*p)
74		p++;
75
76	for (i = 0; i < NT_SID_AUTH_MAX; ++i) {
77		if (sid->sid_authority[i] != 0 || i == NT_SID_AUTH_MAX - 1) {
78			(void) sprintf(p, "%d", sid->sid_authority[i]);
79			while (*p)
80				p++;
81		}
82	}
83
84	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
85		(void) sprintf(p, "-%u", sid->sid_subauth[i]);
86		while (*p)
87			p++;
88	}
89}
90
91/*
92 * sid_fromstr
93 *
94 * Converts a SID in string form to a SID structure. There are lots of
95 * simplifying assumptions in here. The memory for the SID is allocated
96 * as if it was the largest possible SID; the caller is responsible for
97 * freeing the memory when it is no longer required. We assume that the
98 * string starts with "S-1-" and that the authority is held in the last
99 * byte, which should be okay for most situations. It also assumes the
100 * sub-authorities are in decimal format.
101 *
102 * On success, a pointer to a SID is returned. Otherwise a null pointer
103 * is returned.
104 */
105sid_t *
106sid_fromstr(char *sidstr)
107{
108	sid_t *sid;
109	char *p;
110	int size;
111	uint8_t i;
112
113	if (sidstr == NULL)
114		return (NULL);
115
116	if (strncmp(sidstr, "S-1-", 4) != 0)
117		return (NULL);
118
119	size = sizeof (sid_t) + (NT_SID_SUBAUTH_MAX * sizeof (uint32_t));
120
121	if ((sid = malloc(size)) == NULL)
122		return (NULL);
123
124	bzero(sid, size);
125	sid->sid_revision = NT_SID_REVISION;
126	sid->sid_authority[5] = atoi(&sidstr[4]);
127
128	for (i = 0, p = &sidstr[5]; i < NT_SID_SUBAUTH_MAX && *p; ++i) {
129		while (*p && *p == '-')
130			++p;
131
132		if (*p < '0' || *p > '9') {
133			free(sid);
134			return (NULL);
135		}
136
137		sid->sid_subauth[i] = strtoul(p, NULL, 10);
138
139		while (*p && *p != '-')
140			++p;
141	}
142
143	sid->sid_subauthcnt = i;
144	return (sid);
145}
146
147void
148sid_free(sid_t *sid)
149{
150#ifdef _KERNEL
151	if (sid == NULL)
152		return;
153
154	kmem_free(sid, sid_len(sid));
155#else
156	free(sid);
157#endif
158}
159
160void
161sid_to_le(sid_t *sid)
162{
163	int i;
164
165	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
166		uint32_t v = sid->sid_subauth[i];
167		uint8_t *p = (uint8_t *)&sid->sid_subauth[i];
168
169		p[0] = v & 0xff;
170		p[1] = (v >> 8) & 0xff;
171		p[2] = (v >> 16) & 0xff;
172		p[3] = (v >> 24) & 0xff;
173	}
174}
175
176void
177sid_from_le(sid_t *sid)
178{
179	int i;
180
181	for (i = 0; i < sid->sid_subauthcnt && i < NT_SID_SUBAUTH_MAX; ++i) {
182		uint32_t v;
183		uint8_t *p = (uint8_t *)&sid->sid_subauth[i];
184
185		v = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
186
187		sid->sid_subauth[i] = v;
188	}
189}
190