1 /* groupserv - group services.
2  * Copyright (c) 2010 Atheme Development Group
3  */
4 
5 #include "groupserv_main.h"
6 
7 #define GDBV_VERSION	4
8 
9 static unsigned int loading_gdbv = -1;
10 static unsigned int their_ga_all;
11 
write_groupdb(database_handle_t * db)12 static void write_groupdb(database_handle_t *db)
13 {
14 	myentity_t *mt;
15 	myentity_iteration_state_t state;
16 	mowgli_patricia_iteration_state_t state2;
17 	metadata_t *md;
18 
19 	db_start_row(db, "GDBV");
20 	db_write_uint(db, GDBV_VERSION);
21 	db_commit_row(db);
22 
23 	db_start_row(db, "GFA");
24 	db_write_word(db, gflags_tostr(ga_flags, GA_ALL));
25 	db_commit_row(db);
26 
27 	MYENTITY_FOREACH_T(mt, &state, ENT_GROUP)
28 	{
29 		mowgli_node_t *n;
30 
31 		continue_if_fail(mt != NULL);
32 		mygroup_t *mg = group(mt);
33 		continue_if_fail(mg != NULL);
34 
35 		char *mgflags = gflags_tostr(mg_flags, mg->flags);
36 
37 		db_start_row(db, "GRP");
38 		db_write_word(db, entity(mg)->id);
39 		db_write_word(db, entity(mg)->name);
40 		db_write_time(db, mg->regtime);
41 		db_write_word(db, mgflags);
42 		db_commit_row(db);
43 
44 		MOWGLI_ITER_FOREACH(n, mg->acs.head)
45 		{
46 			groupacs_t *ga = n->data;
47 			char *flags = gflags_tostr(ga_flags, ga->flags);
48 
49 			db_start_row(db, "GACL");
50 			db_start_row(db, entity(mg)->name);
51 			db_start_row(db, ga->mt->name);
52 			db_start_row(db, flags);
53 			db_commit_row(db);
54 		}
55 
56 		if (object(mg)->metadata)
57 		{
58 			MOWGLI_PATRICIA_FOREACH(md, &state2, object(mg)->metadata)
59 			{
60 				db_start_row(db, "MDG");
61 				db_write_word(db, entity(mg)->name);
62 				db_write_word(db, md->name);
63 				db_write_str(db, md->value);
64 				db_commit_row(db);
65 			}
66 		}
67 	}
68 }
69 
db_h_gdbv(database_handle_t * db,const char * type)70 static void db_h_gdbv(database_handle_t *db, const char *type)
71 {
72 	loading_gdbv = db_sread_uint(db);
73 	slog(LG_INFO, "groupserv: opensex data schema version is %d.", loading_gdbv);
74 
75 	their_ga_all = GA_ALL_OLD;
76 }
77 
db_h_gfa(database_handle_t * db,const char * type)78 static void db_h_gfa(database_handle_t *db, const char *type)
79 {
80 	const char *flags = db_sread_word(db);
81 
82 	gflags_fromstr(ga_flags, flags, &their_ga_all);
83 	if (their_ga_all & ~GA_ALL)
84 	{
85 		slog(LG_ERROR, "db-h-gfa: losing flags %s from file", gflags_tostr(ga_flags, their_ga_all & ~GA_ALL));
86 	}
87 	if (~their_ga_all & GA_ALL)
88 	{
89 		slog(LG_ERROR, "db-h-gfa: making up flags %s not present in file", gflags_tostr(ga_flags, ~their_ga_all & GA_ALL));
90 	}
91 }
92 
db_h_grp(database_handle_t * db,const char * type)93 static void db_h_grp(database_handle_t *db, const char *type)
94 {
95 	mygroup_t *mg;
96 	const char *uid = NULL;
97 	const char *name;
98 	time_t regtime;
99 	const char *flagset;
100 
101 	if (loading_gdbv >= 4)
102 		uid = db_sread_word(db);
103 
104 	name = db_sread_word(db);
105 
106 	if (mygroup_find(name))
107 	{
108 		slog(LG_INFO, "db-h-grp: line %d: skipping duplicate group %s", db->line, name);
109 		return;
110 	}
111 	if (uid && myentity_find_uid(uid))
112 	{
113 		slog(LG_INFO, "db-h-grp: line %d: skipping group %s with duplicate UID %s", db->line, name, uid);
114 		return;
115 	}
116 
117 	regtime = db_sread_time(db);
118 
119 	mg = mygroup_add_id(uid, name);
120 	mg->regtime = regtime;
121 
122 	if (loading_gdbv >= 3)
123 	{
124 		flagset = db_sread_word(db);
125 
126 		if (!gflags_fromstr(mg_flags, flagset, &mg->flags))
127 			slog(LG_INFO, "db-h-grp: line %d: confused by flags: %s", db->line, flagset);
128 	}
129 }
130 
db_h_gacl(database_handle_t * db,const char * type)131 static void db_h_gacl(database_handle_t *db, const char *type)
132 {
133 	mygroup_t *mg;
134 	myentity_t *mt;
135 	unsigned int flags = GA_ALL;	/* GDBV 1 entires had full access */
136 
137 	const char *name = db_sread_word(db);
138 	const char *entity = db_sread_word(db);
139 	const char *flagset;
140 
141 	mg = mygroup_find(name);
142 	mt = myentity_find(entity);
143 
144 	if (mg == NULL)
145 	{
146 		slog(LG_INFO, "db-h-gacl: line %d: groupacs for nonexistent group %s", db->line, name);
147 		return;
148 	}
149 
150 	if (mt == NULL)
151 	{
152 		slog(LG_INFO, "db-h-gacl: line %d: groupacs for nonexistent entity %s", db->line, entity);
153 		return;
154 	}
155 
156 	if (loading_gdbv >= 2)
157 	{
158 		flagset = db_sread_word(db);
159 
160 		if (!gflags_fromstr(ga_flags, flagset, &flags))
161 			slog(LG_INFO, "db-h-gacl: line %d: confused by flags: %s", db->line, flagset);
162 
163 		/* ACL view permission was added, so make up the permission (#279), but only if the database
164 		 * is from atheme 7.1 or earlier. --kaniini
165 		 */
166 		if (!(their_ga_all & GA_ACLVIEW) && ((flags & GA_ALL_OLD) == their_ga_all))
167 			flags |= GA_ACLVIEW;
168 	}
169 
170 	groupacs_add(mg, mt, flags);
171 }
172 
db_h_mdg(database_handle_t * db,const char * type)173 static void db_h_mdg(database_handle_t *db, const char *type)
174 {
175 	const char *name = db_sread_word(db);
176 	const char *prop = db_sread_word(db);
177 	const char *value = db_sread_str(db);
178 	void *obj = NULL;
179 
180 	obj = mygroup_find(name);
181 
182 	if (obj == NULL)
183 	{
184 		slog(LG_INFO, "db-h-mdg: attempting to add %s property to non-existant object %s",
185 		     prop, name);
186 		return;
187 	}
188 
189 	metadata_add(obj, prop, value);
190 }
191 
gs_db_init(void)192 void gs_db_init(void)
193 {
194 	hook_add_db_write_pre_ca(write_groupdb);
195 
196 	db_register_type_handler("GDBV", db_h_gdbv);
197 	db_register_type_handler("GRP", db_h_grp);
198 	db_register_type_handler("GACL", db_h_gacl);
199 	db_register_type_handler("MDG", db_h_mdg);
200 	db_register_type_handler("GFA", db_h_gfa);
201 }
202 
gs_db_deinit(void)203 void gs_db_deinit(void)
204 {
205 	hook_del_db_write_pre_ca(write_groupdb);
206 
207 	db_unregister_type_handler("GDBV");
208 	db_unregister_type_handler("GRP");
209 	db_unregister_type_handler("GACL");
210 	db_unregister_type_handler("MDG");
211 	db_unregister_type_handler("GFA");
212 }
213