1#include <membership.h>
2
3#include "open_directory.h"
4
5ODNodeRef
6CreateNode(void)
7{
8	CFErrorRef error = NULL;
9	ODNodeRef node = NULL;
10
11	node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODTypeAuthenticationSearchNode, &error);
12
13	if (node == NULL) {
14		CFShow(error);
15		exit(1);
16	}
17
18	return node;
19}
20
21static ODRecordRef
22CopyRecordWithUUID(ODNodeRef node, CFStringRef type, uuid_t uuid)
23{
24	CFErrorRef error = NULL;
25	char uuidstr[37];
26	CFStringRef uuidref;
27	ODQueryRef query = NULL;
28	CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
29	CFArrayRef attributes = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks);
30	CFArrayRef results = NULL;
31	ODRecordRef record = NULL;
32
33	uuid_unparse(uuid, uuidstr);
34	uuidref = CFStringCreateWithCString(NULL, uuidstr, kCFStringEncodingUTF8);
35
36	if (uuidref) {
37		query = ODQueryCreateWithNode(NULL, node, type, CFSTR(kDS1AttrGeneratedUID), kODMatchEqualTo, uuidref, attributes, 100, &error);
38
39		if (query) {
40			results = ODQueryCopyResults(query, false, &error);
41
42			if (results) {
43				if (CFArrayGetCount(results) == 1) {
44					record = (ODRecordRef)CFArrayGetValueAtIndex(results, 0);
45					CFRetain(record);
46				}
47
48				CFRelease(results);
49			}
50
51			CFRelease(query);
52		}
53
54		CFRelease(uuidref);
55	}
56
57	return record;
58}
59
60ODRecordRef
61CopyGroupRecordWithGID(ODNodeRef node, gid_t gid)
62{
63	uuid_t uuid;
64
65	mbr_gid_to_uuid(gid, uuid);
66
67	return CopyRecordWithUUID(node, CFSTR(kDSStdRecordTypeGroups), uuid);
68}
69
70ODRecordRef
71CopyUserRecordWithUID(ODNodeRef node, uid_t uid)
72{
73	uuid_t uuid;
74
75	mbr_uid_to_uuid(uid, uuid);
76
77	return CopyRecordWithUUID(node, CFSTR(kDSStdRecordTypeUsers), uuid);
78}
79
80ODRecordRef
81CopyUserRecordWithUsername(ODNodeRef node, char *name)
82{
83	CFStringRef nameref;
84	CFTypeRef vals[] = { CFSTR(kDSAttributesStandardAll) };
85	CFArrayRef attributes = CFArrayCreate(NULL, vals, 1, &kCFTypeArrayCallBacks);
86	CFErrorRef error;
87
88	nameref = CFStringCreateWithCString(NULL, name, kCFStringEncodingUTF8);
89
90	if (nameref == NULL)
91		return NULL;
92
93	return ODNodeCopyRecord(node, CFSTR(kDSStdRecordTypeUsers), nameref, attributes, &error);
94}
95
96CFStringRef
97CopyAttrFromRecord(ODRecordRef record, CFStringRef attribute)
98{
99	CFErrorRef error = NULL;
100	CFArrayRef values = ODRecordCopyValues(record, attribute, &error);
101	CFStringRef result = NULL;
102
103	if (values) {
104		if (CFArrayGetCount(values) == 1) {
105			result = CFArrayGetValueAtIndex(values, 0);
106			CFRetain(result);
107		}
108		CFRelease(values);
109	}
110
111	return result;
112}
113
114int
115GetIntAttrFromRecord(ODRecordRef record, CFStringRef attribute, int *output)
116{
117	int status = 1;
118	CFStringRef str = CopyAttrFromRecord(record, attribute);
119
120	if (str) {
121		*output = CFStringGetIntValue(str);
122		status = 0;
123		CFRelease(str);
124	}
125
126	return status;
127}
128
129uid_t
130GetUIDFromRecord(ODRecordRef record)
131{
132	int uid = -1;
133
134	GetIntAttrFromRecord(record, CFSTR(kDS1AttrUniqueID), &uid);
135
136	return uid;
137}
138
139gid_t
140GetGIDFromRecord(ODRecordRef record)
141{
142	int gid = -1;
143
144	GetIntAttrFromRecord(record, CFSTR(kDS1AttrPrimaryGroupID), &gid);
145
146	return gid;
147}
148
149CFArrayRef
150CopyGroupRecordsForUser(ODNodeRef node, ODRecordRef user, CFIndex limit)
151{
152	CFMutableArrayRef groups;
153	gid_t primary_gid;
154	ODRecordRef primary_group;
155	CFErrorRef error = NULL;
156	ODQueryRef query;
157	CFArrayRef results;
158	int i;
159	ODRecordRef gr;
160
161	query = ODQueryCreateWithNode(NULL, node, CFSTR(kDSStdRecordTypeGroups),
162		CFSTR(kDSNAttrMember), kODMatchContains, ODRecordGetRecordName(user), NULL, limit, &error);
163	results = ODQueryCopyResults(query, false, &error);
164	CFRelease(query);
165
166	groups = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
167
168	primary_gid = GetGIDFromRecord(user);
169	primary_group = CopyGroupRecordWithGID(node, primary_gid);
170	CFArrayAppendValue(groups, primary_group);
171	CFRelease(primary_group);
172
173	for (i = 0; i < CFArrayGetCount(results); i++) {
174		gr = (ODRecordRef)CFArrayGetValueAtIndex(results, i);
175		if (GetGIDFromRecord(gr) != primary_gid) {
176			CFArrayAppendValue(groups, gr);
177		}
178	}
179
180	CFRelease(results);
181
182	return groups;
183}
184
185static int
186cvfprintf(FILE *file, const char *format, va_list args)
187{
188		char* cstr;
189		int result = 0;
190        CFStringRef formatStr = CFStringCreateWithCStringNoCopy(NULL, format, kCFStringEncodingUTF8, kCFAllocatorNull);
191		if (formatStr) {
192			CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, formatStr, args);
193			if (str) {
194				size_t size = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8) + 1;
195				cstr = malloc(size);
196				if (cstr && CFStringGetCString(str, cstr, size, kCFStringEncodingUTF8)) {
197					result = fprintf(file, "%s", cstr);
198					free(cstr);
199				}
200				CFRelease(str);
201			}
202			CFRelease(formatStr);
203		}
204		return result;
205}
206
207int
208cfprintf(FILE *file, const char *format, ...)
209{
210	int result;
211	va_list args;
212
213	va_start(args, format);
214	result = cvfprintf(file, format, args);
215	va_end(args);
216	return result;
217}
218
219int
220cprintf(const char *format, ...)
221{
222	int result;
223	va_list args;
224
225	va_start(args, format);
226	result = cvfprintf(stdout, format, args);
227	va_end(args);
228	return result;
229}
230