File TODO changed (mode: 100644) (index 259c7b1..8daa2f2) |
1 |
1 |
== Where I stopped last time == |
== Where I stopped last time == |
2 |
|
[ ] |
|
|
2 |
|
[ ] ldap: func test when ldap_password changes, but we have the user inserted |
|
3 |
|
in 'users' |
|
4 |
|
[ ] Will the moving of user_edit_no_check call into ldap would simplify code? |
|
5 |
|
[ ] Can I update users.plan_id on demand, when user logs in? |
|
6 |
|
No, because the statistics are not good! |
|
7 |
|
[ ] If we change the 'uid' attribute, we must invalidate the whole cache. |
|
8 |
|
But, we cannot delete anything. We need the link between uuid and uid. |
|
9 |
|
Just mark it as unavailable. |
|
10 |
|
[ ] Recover password must be enabled for ldap users? |
|
11 |
|
[ ] 'deleted' field must be respected by ldap? |
|
12 |
|
If admin blocks/deletes/suspends an ldap account, what should we do? |
|
13 |
|
[ ] I think I should not allow the login by e-mail! If user can change the |
|
14 |
|
e-mail in LDAP, I have a problem. I think I can keep it. |
|
15 |
|
The password must match. Check! |
|
16 |
|
What about recovering e-mail? |
|
17 |
|
[ ] memberof must be stored in ldap_cache. |
|
18 |
|
[ ] rg_ldap_session_time to be set by the ldap server add form. |
|
19 |
|
[ ] Password must be sent encrypted from ldap_cache to 'users' (update_no_check)). |
|
20 |
|
[ ] When getting data from cache, I have to populate correctly the $ui. |
|
21 |
|
It is a valid case for replication: we will have entries in |
|
22 |
|
ldap_cache with 'uid' 0. |
|
23 |
|
[ ] ldap: we do not have the membership and we cannot extract is_admin. |
|
24 |
|
Probably other fields. |
|
25 |
|
[ ] ldap: ce se intimpla daca schimb cimpul 'uid'? Sa permit asta? |
|
26 |
|
Probably I have to clean the cache. |
|
27 |
|
Because I do not store all fields in cache and the new uid field |
|
28 |
|
probably is missing. Maybe I should test if the field is present and |
|
29 |
|
do not delete the cache? Neh... But, if I delete the cache, I lose |
|
30 |
|
the links between 'users' and ldap_cache! |
|
31 |
|
Mark the ldap_cache entries as 'stalled' and use them only to link to |
|
32 |
|
uid? |
|
33 |
|
[ ] ldap: default for uid_attr is uid? |
|
34 |
|
[ ] ldap: what rights should I give for users added by ldap? |
|
35 |
|
[ ] Pass also the ldap server info, next to 'post', to be able to update |
|
36 |
|
plan_id. |
|
37 |
|
[ ] ldap: ldap_login: user not found in cache, binding is ok, we are at the |
|
38 |
|
end of the function. We should store $ui in cache, but we do not have |
|
39 |
|
the users.uid! What to do?! Should I return $ui and insert the user |
|
40 |
|
in users and call a callback to update the cache because we have the |
|
41 |
|
users.uid? Should it be in a transaction? |
|
42 |
|
So login_by_user_pass |
|
43 |
|
try to find in in users.db |
|
44 |
|
if not found |
|
45 |
|
try to search it in ldap_cache |
|
46 |
|
if not found |
|
47 |
|
search on ldap server |
|
48 |
|
if found |
|
49 |
|
return $ui |
|
50 |
|
now, we have $ui, but the uid may be 0 |
|
51 |
|
if 0 |
|
52 |
|
insert the new user in database |
|
53 |
|
call a callback to update ldap_cache with the |
|
54 |
|
uid. |
|
55 |
|
should not be in transaction, because next |
|
56 |
|
time we will return without uid and we will do |
|
57 |
|
an insert into db. NOT GOOD! We must not |
|
58 |
|
duplicate users (anyway, it wouldn't work). |
|
59 |
|
So, we need a transaction. But, what happends |
|
60 |
|
when we delete stuff from the ldap_cache?! |
|
61 |
|
Should we mark the users as deleted? |
|
62 |
|
Should I use the uuid to not update ldap_cache? |
|
63 |
|
|
|
64 |
|
If I do link 'users' and 'ldap_cache' by uid: |
|
65 |
|
I have to call a 'post' callback, in a transaction to also update ldap_cache.uid |
|
66 |
|
Nope. Cannot work. Another login will try to insert the same username. |
|
67 |
|
Transactions cannot help! |
|
68 |
|
|
|
69 |
|
CPU1 CPU2 |
|
70 |
|
SELECT FROM users WHERE username = ... |
|
71 |
|
SELECT FROM ldap_cache (not found) |
|
72 |
|
SELECT FROM users WHERE username = ... |
|
73 |
|
SELECT FROM ldap_cache (not found) |
|
74 |
|
INSERT INTO users (ok) |
|
75 |
|
INSERT INTO users (fail) |
|
76 |
|
|
|
77 |
|
If I link them by uuid: |
|
78 |
|
- No 'post' hook needed |
|
79 |
|
- At login time, ldap_cache will give the uuid and I have to |
|
80 |
|
search by it in users table. Ugly. |
|
81 |
|
For both, I have to update users.username field if different. Event? |
|
82 |
|
|
|
83 |
|
I can use an advisory lock. |
|
84 |
|
|
|
85 |
|
Let's see what happens if I link by uuid: |
|
86 |
|
first login: ldap_cache is emty |
|
87 |
|
ldap_login is called |
|
88 |
|
cache is empty, so I continue |
|
89 |
|
bind correctly in ldap |
|
90 |
|
insert into ldap_cache(..., uuid, ...) |
|
91 |
|
return $ui with everything from ldap |
|
92 |
|
insert into users with external_id = uuid |
|
93 |
|
second login: ldap_cache has the user now |
|
94 |
|
ldap_login is called |
|
95 |
|
found in users |
|
96 |
|
third login: users entry expired |
|
97 |
|
found in users but is expired |
|
98 |
|
ldap_login is called |
|
99 |
|
return $ui with everything from ldap_cache |
|
100 |
|
|
|
101 |
|
CPU1 CPU2 CPU3 |
|
102 |
|
SELECT FROM users (by username/pass) |
|
103 |
|
SELECT FROM users (by username/pass) |
|
104 |
|
SELECT FROM ldap_cache (by ?) (not found) |
|
105 |
|
ldap_bind & co. |
|
106 |
|
SELECT FROM ldap_cache (not found) |
|
107 |
|
ldap_bind & co. |
|
108 |
|
LOCK ldap_cache |
|
109 |
|
LOCK ldap_cache |
|
110 |
|
SELECT FROM ldap_cache (not found) |
|
111 |
|
INSERT INTO users (ok) - to find the uid; nobody can do it concurrently! |
|
112 |
|
INSERT INTO ldap_cache (...uid/uuid...) |
|
113 |
|
UNLOCK ldap_cache |
|
114 |
|
SELECT FROM ldap_cache (found) SELECT FROM users (by username/pass) (expired) |
|
115 |
|
SELECT FROM ldap_cache (found) |
|
116 |
|
UNLOCK ldap_cache |
|
117 |
|
|
|
118 |
|
I should try to do a select in ldap_cache, if not found lock the table, |
|
119 |
|
do again the select in ldap_cache (someone may insert between select and lock). |
|
120 |
|
So, if found in cache, I will not lock the table. |
|
121 |
|
One problem: I should not do the bind with the lock taken. Fixed. |
|
122 |
|
|
|
123 |
|
If I use uuid, when the ldap_cache returns something, I have to do |
|
124 |
|
a select in db after uuid to obtain the entry! |
|
125 |
|
Another query, another index... |
|
126 |
|
|
|
127 |
|
What if I would insert into ldap_cache, under lock and then return? |
|
128 |
|
Then, two threads will try to insert into 'users'! |
|
129 |
|
|
|
130 |
|
What if I link 'users' and 'ldap_cache' by username?! |
3 |
131 |
|
|
|
132 |
|
=== New plan: ignore 'duplicate unique' errors === |
|
133 |
|
CPU1 |
|
134 |
|
SELECT FROM users (by username/pass) (not found / expired) |
|
135 |
|
SELECT FROM ldap_cache (by mail/ldap_uid/cn) (not found / expired) |
|
136 |
|
contact ldap server (binding/search) |
|
137 |
|
INSERT INTO ldap_cache (...uid/uuid...) |
|
138 |
|
INSERT INTO users (ok) - to find the uid; ignore error |
|
139 |
|
apelez un callback care face update la ldap_cache.uid? |
|
140 |
|
|
|
141 |
|
Pot insera in cache prima data (ce se intimpla daca e deja? update?) |
|
142 |
|
Problema e ca e posibil sa nu gasesc row-ul in 'users' ca |
|
143 |
|
sa-i fac update si inserez unul nou. Ar trebui sa-l caut mai |
|
144 |
|
intii. As putea face update si daca nu merge sa fac insert. |
|
145 |
|
Dar, la update, ce WHERE folosesc? external_id? |
|
146 |
|
|
|
147 |
|
[ ] ldap: we may want to check AuthLDAPGroupAttributeIsDN from apache. |
|
148 |
|
[ ] ldap: should we have a 'source' field in users table to signal from where |
|
149 |
|
the user come from (web, ldap etc.)? |
|
150 |
|
[ ] ldap: When updating a server prio, we have to update also the ldap_cache |
|
151 |
|
table. Should I use a JOIN to get rid of ldap_cache.prio? |
|
152 |
|
[ ] ldap: Do not store password in clear in database! |
|
153 |
|
[ ] ldap: add a timeout for every server. |
|
154 |
|
[ ] ldap: gather all sync stuff and commit in the end for sync=ro? |
|
155 |
|
[ ] ldap: take care to not allow logins as admins if the group name is user |
|
156 |
|
controlled. Should we use ^/$ by default? |
|
157 |
|
[ ] ldap: https://github.com/thorin/redmine_ldap_sync |
|
158 |
|
As an example which works also on AD. |
|
159 |
|
[ ] ldap: how to specify if an account is disabled? Some regex needed? |
|
160 |
|
[ ] ldap: server settings: select between one level or subtree. |
|
161 |
|
[ ] ldap: what indexes are needed for ldap_* tables? |
|
162 |
|
[ ] ldap: Remember, I may have the full ldap db in ldap_cache table, |
|
163 |
|
without a link with uid! When a ldap users login for the first time, |
|
164 |
|
I can do the link (store uid in ldap_cache table). |
|
165 |
|
[ ] ldap: I have to learn entryUUID now! |
|
166 |
|
[ ] ldap: when a user logins, she/he uses the e-mail, or uid or something |
|
167 |
|
decided by LDAP admin. |
|
168 |
|
I have to identify the user in 'users'. How can I? |
|
169 |
|
With a table containing: |
|
170 |
|
server_id [3] - to be able to remove a server or to not have clashes? |
|
171 |
|
uid [55] - may be 0 if the user did not logged in yet |
|
172 |
|
ldap_uid [catalinux] |
|
173 |
|
userPassword [] - we must be able to decrypt it using the same algo |
|
174 |
|
sn |
|
175 |
|
givenName |
|
176 |
|
gidNumber |
|
177 |
|
entryUUID [12345-12345-12345-12345-12345] |
|
178 |
|
- to be used when sync data |
|
179 |
|
mail [catalinux@rocketgit.com] |
|
180 |
|
Do not forget about the groups! |
|
181 |
|
When a user connects, I need to search by one of the ldap attributes |
|
182 |
|
to obtain the uid, then: |
|
183 |
|
if password is not valid, search next entry. |
|
184 |
|
if ldap_cache.uid == 0, insert a new entry in 'users' table and update ldap_cache.uid |
|
185 |
|
if ldap_cache.uid != 0, we have the uid |
|
186 |
|
Can we optimize the search? |
|
187 |
|
[] We should try another entry/server if the password does not match. |
|
188 |
|
[ ] ldap: somehow delete old ldap servers. Also from cache. |
|
189 |
|
[ ] ldap: test: login by email. |
|
190 |
|
[ ] ldap: user logins by DN, and, of course, I cannot find it in the database. |
|
191 |
|
I have to search for it based on entryUUID. |
|
192 |
|
[ ] ldap: now the dilemma is how to add a user from inside ldap_login function! |
|
193 |
|
Should we return a special flag which instructs the login function |
|
194 |
|
to add the user? |
|
195 |
|
[ ] ldap: what plan should have the users? Select it when adding the servers. |
|
196 |
|
What if the plan is gone? Use the first one and notify admin? |
|
197 |
|
[ ] ldap: now, what field will be the future username in db? uid? Configurable? |
|
198 |
|
[ ] ldap: admin: add servers |
|
199 |
|
Should we have a daemon to sync with the ldap server? |
|
200 |
|
[ ] When upgrading and cache was not up, on rocketgit.com, logged in as admin |
|
201 |
|
it asked about initial account! This is not good! |
|
202 |
|
[ ] 'meronos' user is with lower 'm', but in the /var/lib/rocketgit/repos/ |
|
203 |
|
folder is with bigger M! Does he renamed the user and I did not updated |
|
204 |
|
the link? |
|
205 |
|
[ ] wh:build: output is not collected. |
|
206 |
|
[ ] Lots of errors of this type: |
|
207 |
|
16056 ? D 16:47 git --no-pager |
|
208 |
|
--git-dir=/var/lib/rocketgit/repos/by_id/00/00/00/7B/0000007B/ |
|
209 |
|
repos/by_id/125.git log --find-copies --find-renames |
|
210 |
|
--find-copies-harder --no-merges --numstat -z |
|
211 |
|
--pretty=format:-=ROCKETGIT-START-5ab66aa6dd48474e=-sha1:%H%x00 |
|
212 |
|
sha1_short:%h%x00tree:%T%x00tree_short:%t%x00parents:%P%x00 |
|
213 |
|
parents_short:%p%x00author name:%aN%x00author email:%aE%x00 |
|
214 |
|
author date:%at%x00committer name:%cN%x00committer email:%ce%x00 |
|
215 |
|
committer date:%ct%x00encoding:%e%x00ref_names:%d%x00 |
|
216 |
|
sign_key:%GK%x00subject:%s%x00body:%b%x00notes:%N%x00 |
|
217 |
|
-=ROCKETGIT_END_OF_VARS-5ab66aa6dd48474e=- |
|
218 |
|
[ ] Prevent repos to start with '-'? (Git security issue) |
|
219 |
|
[ ] Allow download of files in the repo. |
|
220 |
|
[ ] Username must not contain '::' to not break cache! |
|
221 |
|
Hm. Any string containing :: is at risk?! Or the = makes the diff? |
|
222 |
|
[ ] Plan for LDAP sync: |
|
223 |
|
Should I have a different password in 'users' table for backup? |
|
224 |
|
I have to create the users. |
|
225 |
|
I have to take it step by step: |
|
226 |
|
All posible LDAP servers are verified by priority |
|
227 |
|
All servers have some flags (or a single) type: |
|
228 |
|
- if a direct connection is made (with or without cache) |
|
229 |
|
- if ro repl is used |
|
230 |
|
- if rp repl is used |
|
231 |
|
But, all may be used. ro/rp replications are pretty the same. |
|
232 |
|
Direct connection should be used if anything fails. |
|
233 |
|
The cache may be used only if admin decided on how many seconds |
|
234 |
|
a cache is valid. |
|
235 |
|
ro/rp repl should populate the cache only - a user must |
|
236 |
|
not be created in db if the user did not login. |
|
237 |
|
So, a user tries to login: |
|
238 |
|
- check database - first time the user is not there |
|
239 |
|
Second time? |
|
240 |
|
Should we mark the entry as being ldap? |
|
241 |
|
- go to ldap function |
|
242 |
|
- select in ldap cache table if a user is matching (order prio) |
|
243 |
|
- if not found, do a direct lookup |
|
244 |
|
- update the database? |
|
245 |
|
We must insert into database to obtain the uid. |
|
246 |
|
The sync process will update the database if needed (entryUUID). |
4 |
247 |
|
|
5 |
248 |
== BEFORE NEXT RELEASE == |
== BEFORE NEXT RELEASE == |
|
249 |
|
[ ] Add compression for JS/CSS. Think about enabling compression for html, |
|
250 |
|
but, implement some randomization on content to defend against BREACH. |
|
251 |
|
For CSRF tokens there is a simple and effective defence, which is to randomize the token by masking it with a different (random) value on every response. The masking does not hide the token (whoever has the token can easily reverse the masking), but it does defeat the attack technique. Guessing is impossible when the secret is changing all the time. Thus, we can expect that most frameworks will adopt this technique. Those who rely on frameworks will only need to upgrade to take advantage of the defence. Those who don’t will have to fix their code. |
|
252 |
|
(https://blog.qualys.com/ssllabs/2013/08/07/defending-against-the-breach-attack) |
|
253 |
|
|
|
254 |
|
[ ] Implement https://github.com/privacypass/challenge-bypass-extension |
|
255 |
|
[ ] ldap: test nested groups. |
|
256 |
|
[ ] 2fa: admin must be able to enforce it! |
|
257 |
|
[ ] Have a user setting / button to create a diff without space clean-up. |
|
258 |
|
[ ] detect big patches can return 'bad' and no good_files, but the simple log |
|
259 |
|
is still called! Not good! Functional test! |
|
260 |
|
[ ] Go to groups.google.com and create a group for rocketgit? |
|
261 |
|
[ ] I like the forms on http://cc1.ifj.edu.pl/en/ |
|
262 |
|
[ ] Cache HTTP credentials: |
|
263 |
|
git config --global credential.helper cache |
|
264 |
|
[ ] Adopt DCO: https://developercertificate.org/ |
|
265 |
|
[ ] periodically run 'git fsck'. |
|
266 |
|
[ ] ssh: 'UseDNS no' (docker / virtual machine etc.) to speed up the connection. |
|
267 |
|
[ ] |
|
268 |
|
[ ] Allow multiple branches in the pull request |
|
269 |
|
[ ] Enable HTTP/2 (as the tests)! |
|
270 |
|
[ ] ldap: what to do with the ldap users when their server is removed? |
|
271 |
|
[ ] Add a hint to login page that, with ldap, you can login also with mail/cn. |
|
272 |
|
[ ] Allow user to choose if the real name is public or not? |
|
273 |
|
[ ] Support https://www.microcosm.co.uk/order/product.php?ProductID=360&CurrencyID=3 |
|
274 |
|
[ ] I should fail the test phase if err- files are generated? |
|
275 |
|
What about server side? |
|
276 |
|
[ ] Add labels for projects. |
|
277 |
|
[ ] When creating a repo, refuse to end in '.git'. I strip it sometimes (tekker user)! |
|
278 |
|
[ ] Get rid of links in /var/lib/rocketgit/repos, to not deal with renames etc. |
|
279 |
|
[ ] I need a mechanism to verify an account expiration, even if a session |
|
280 |
|
is active. Think about marking an account to expire at some moment |
|
281 |
|
in time. We have shadowExpire for LDAP, but we must be able to do it |
|
282 |
|
also for normal accounts. The field is 'expire'. And maybe give up on |
|
283 |
|
'suspended' field? |
|
284 |
|
Do we really test if an account is suspended? |
|
285 |
|
Maybe is better to reuse 'suspended'. |
|
286 |
|
[ ] Add timezone setting? |
|
287 |
|
[ ] For authorize script, why we do not use the cache? |
|
288 |
|
[ ] ldap: what session time to use? Use default, but let the user change? |
|
289 |
|
[ ] Welcome e-mail may contain links to tutorials/api etc. |
|
290 |
|
[ ] Should we store the server next to a ldap user to be able to look up |
|
291 |
|
the timeout value? Or just store the expiration into users table? |
|
292 |
|
What about entryUUID, the only thing that links ldap with db. |
|
293 |
|
What if user is renamed? Should I give up on keeping links, |
|
294 |
|
but, for admins, show the path to the repo. |
|
295 |
|
[ ] ui['rights'] is still used? If yes, set them also for ldap. |
|
296 |
|
[ ] Add a functional test to see if the request for e-mail confirmation is |
|
297 |
|
shown on the page. And move it from hints to somewhere near the top. |
|
298 |
|
[ ] ask_for_email_confirmation and rg_account_email_confirm do same thing? |
|
299 |
|
[ ] Use sshd's ExposeAuthInfo to log some nice info. |
|
300 |
|
[ ] We should never redirect using an empty string. |
|
301 |
|
[ ] ldap: loop if password does not mach for an user. |
|
302 |
|
[ ] ldap: when we find a user, try to bind as that user if first time |
|
303 |
|
we bound with the main one. |
|
304 |
|
[ ] preg_match may return an error. Test for it! |
|
305 |
|
[ ] If I restart the builder server side script, the client will not reconnect! |
|
306 |
|
[ ] compare: granting reverse endorse power? RocketGit: No; GitLab: yes. |
|
307 |
|
[ ] Decide what to do about Frederico request for space. |
|
308 |
|
[ ] Add to home/repo page hints that you can build (CI) your project. |
|
309 |
|
[ ] wh: build: cloning with --depth 1 seems to not allow checking out a specific |
|
310 |
|
commit. Not true. Seems a force push took place. |
|
311 |
|
We should cancel previous builds? |
|
312 |
|
[ ] ldap: sync ssh keys |
|
313 |
|
[ ] ldap: timeout must also be a parameter. |
|
314 |
|
[ ] ldap: forgot function should not work? |
|
315 |
|
[ ] ldap: User changing group => dn changes |
|
316 |
|
[ ] ldap: User changing dn - check if entryDN is of any help. |
|
317 |
|
[ ] artefacts generated by demand, on a special page. |
|
318 |
|
Think about building a CSV file from some files stored in repository. |
|
319 |
|
For example: building a csv list of servers based on some directories |
|
320 |
|
with the server and some files containing some info. |
|
321 |
|
Of course, a sandbox is needed for this. Lua? |
|
322 |
|
[ ] change log id on forking and log this change. |
|
323 |
|
[ ] ldap: limit replication fields to the ones needed. |
|
324 |
|
[ ] ldap: allow admin to move all users to a ldap server (including groups) |
|
325 |
|
[ ] https://stackoverflow.com/questions/28810795/git-clone-is-aborting-due-to-possible-repository-corruption-on-the-remote-side-e/28811605#28811605 |
|
326 |
|
[ ] web: Add 'add_header Cache-Control "public";' to 'public' content |
|
327 |
|
(nginx/location) |
|
328 |
|
[ ] report: add also the load |
|
329 |
|
[ ] Per git configuration, should be exposed to the user |
|
330 |
|
gc.pruneExpire 2.weeks.ago |
|
331 |
|
pack.* |
|
332 |
|
[ ] css: add 'placeholder="some example here"' for some input fields. |
|
333 |
|
[ ] In the report, show also the number of deleted repos. |
|
334 |
|
[ ] We should not allow plan deletion if there are still users. |
|
335 |
|
[ ] started requests without a final "commit" message should be logged as |
|
336 |
|
errors. Think about git operations which does not finish because |
|
337 |
|
PHP is out of memory. At the start and end of the operation we should |
|
338 |
|
send a message. If the 'end' is missing, we know that something is |
|
339 |
|
wrong. |
|
340 |
|
[ ] We should re-think the logging, because some functions are |
|
341 |
|
called multiple times (hundreds) and we do not want |
|
342 |
|
the rg_log_enter string to appear multiple times. |
|
343 |
|
We need to delay the logging somehow and log the pending buffer |
|
344 |
|
only in case of errors. |
|
345 |
|
[ ] Improve the caching of the rights. |
|
346 |
|
[ ] rights: do not log success lookups, only the bad ones. |
|
347 |
|
Too much logging involved! |
|
348 |
|
[ ] Messages from ssh/http transport: log also date and rg_log_sid to be able |
|
349 |
|
to find the problem quickly. |
|
350 |
|
[ ] invite function for a repo - maybe suggest the rights? |
|
351 |
|
Auto create user? (petreb) |
|
352 |
|
[ ] Allow almost any file to be downloaded as pdf. |
|
353 |
|
[ ] wh: build: add time for machine boot-up. |
|
354 |
|
[ ] I have some broken links in the /var/lib/rocketgit/repos folder. |
|
355 |
|
Maybe somebody deleted the repo? Check the logs. |
|
356 |
|
[ ] ssh: wait till first connection is done with AuthorizedKeysCommand |
|
357 |
|
and only after that disable the authorized_keys generation? |
|
358 |
|
[ ] ldap: admin: allow switching between ldap and non-ldap accounts. |
|
359 |
|
Because users may change their e-mail, we should be careful |
|
360 |
|
what we use for ldap authentication. |
|
361 |
|
Should we allow users to update an account to ldap? |
|
362 |
|
[ ] ldap: allow admin to set ssl/starttls per server. |
|
363 |
|
[ ] ldap: server add form: |
|
364 |
|
- type of the server (can we auto detect?) |
|
365 |
|
- host(s) urls (including port) |
|
366 |
|
- bind_dn + pass |
|
367 |
|
- base for search |
|
368 |
|
- which ldap field is used for authentication (sAMAccountName/uid etc.) |
|
369 |
|
- filter (&(objectClass=posixAccount)(uid=...) |
|
370 |
|
we may need to support more user types (e.g. 'user') |
|
371 |
|
- group base |
|
372 |
|
- group attribute ('group', 'posixGroup', 'groupOfNames' etc.) |
|
373 |
|
- admin group |
|
374 |
|
- regex for what groups the users are allowed to use rocketgit |
|
375 |
|
- mapping between ldap attributes and rocketgit user attributes |
|
376 |
|
- if we allow ssh keys from ldap |
|
377 |
|
- enable nested groups |
|
378 |
|
- paged results |
|
379 |
|
- follow referrals |
|
380 |
|
- ca/certificate/key/insecure? |
|
381 |
|
[ ] ldap: sync: use ldapsearch -E sync=ro/rp! |
|
382 |
|
[ ] ldap: respect account expiration set in ldap (shadowExpire etc.) |
|
383 |
|
[ ] ldap: we may allow rocketgit rights to be defined in ldap |
|
384 |
|
[ ] ldap: allow admin to decide the time between syncs. |
|
385 |
|
[ ] ldap: find a way to re-sync more quickly, maybe just looking up |
|
386 |
|
only what changed since the last sync. |
|
387 |
|
Or, use the replication protocol? |
|
388 |
|
[ ] ldap: prevent users to change their settings if the account is linked |
|
389 |
|
with ldap? |
|
390 |
|
[ ] ldap: |
|
391 |
|
http://mageconfig.blogspot.ro/2014/06/configure-gitgerrit-with-open-ldap-for.html |
|
392 |
|
add groups support |
|
393 |
|
[ ] a repo must have a direct link to report a bug. |
|
394 |
|
[ ] Add a functional test for a max commit size bigger than a big number. |
|
395 |
|
[ ] gabi: add API: input: user/pass, out: key for mobile app |
|
396 |
|
[ ] gabi: API: discover, search etc. |
|
397 |
|
[ ] In rg_exec, I can count how many bytes were sent/received! |
|
398 |
|
Expose them in the ssh keys section? |
|
399 |
|
Account them and enfoce some limits? |
6 |
400 |
[ ] rg_ssh_host/rg_git_host must be set also in admin web page. |
[ ] rg_ssh_host/rg_git_host must be set also in admin web page. |
7 |
401 |
[ ] When a file is empty, show it in a special way to not be tempted to click |
[ ] When a file is empty, show it in a special way to not be tempted to click |
8 |
402 |
on it. |
on it. |
9 |
|
[ ] LDAP |
|
10 |
|
http://mageconfig.blogspot.ro/2014/06/configure-gitgerrit-with-open-ldap-for.html |
|
11 |
|
add groups support |
|
12 |
403 |
[ ] hostname problems: |
[ ] hostname problems: |
13 |
404 |
We may want to add a new state (hostname_real) which will be set by |
We may want to add a new state (hostname_real) which will be set by |
14 |
405 |
admin and will have precedence over 'hostname', which is only |
admin and will have precedence over 'hostname', which is only |
15 |
406 |
guessed by first access. If 'hostname_real' is not set, add a warning |
guessed by first access. If 'hostname_real' is not set, add a warning |
16 |
407 |
on all pages for admin user to set the correct hostname. |
on all pages for admin user to set the correct hostname. |
17 |
|
[ ] compare: add number of lines of the project. |
|
18 |
408 |
[ ] For repo stats, add also the number of lines. |
[ ] For repo stats, add also the number of lines. |
19 |
409 |
[ ] Add a minimum password length and enforce it everywhere. |
[ ] Add a minimum password length and enforce it everywhere. |
20 |
410 |
[ ] Never redirect if the Host:'s port is different from SERVER_PORT. |
[ ] Never redirect if the Host:'s port is different from SERVER_PORT. |
21 |
411 |
(see docker with redirects) |
(see docker with redirects) |
22 |
|
[ ] Add also "normal" we page (without virtualhost) |
|
|
412 |
|
[ ] Add also "normal" web page (without virtualhost) |
23 |
413 |
to be able to start with the current server? |
to be able to start with the current server? |
24 |
414 |
[ ] For repo stats, we may want to use --all or --branches. |
[ ] For repo stats, we may want to use --all or --branches. |
25 |
415 |
[ ] When showing a commit, Create links for "Parents"/"Tree". Probably others. |
[ ] When showing a commit, Create links for "Parents"/"Tree". Probably others. |
|
35 |
425 |
[ ] Add AGPL logo to main web page? |
[ ] Add AGPL logo to main web page? |
36 |
426 |
[ ] Add 'depends/number' label to mark some bugs as a dependency on another. |
[ ] Add 'depends/number' label to mark some bugs as a dependency on another. |
37 |
427 |
What about duplicates? Confidential? |
What about duplicates? Confidential? |
38 |
|
[ ] We do no track of the visitors. Also in git announce? |
|
|
428 |
|
[ ] We do no track the visitors. Also in git announce? |
39 |
429 |
[ ] Use 'restrict' when generating authorized_keys file. |
[ ] Use 'restrict' when generating authorized_keys file. |
40 |
430 |
[ ] In report, report also the space used and a top 5? |
[ ] In report, report also the space used and a top 5? |
41 |
431 |
[ ] At login time to destroy all forgot password pending tokens? |
[ ] At login time to destroy all forgot password pending tokens? |
|
123 |
513 |
Maybe replace "History" with "Log" and "Tree" and make the |
Maybe replace "History" with "Log" and "Tree" and make the |
124 |
514 |
select of the branch/tag as a select. |
select of the branch/tag as a select. |
125 |
515 |
This is to not have another menu line. Is overkill. |
This is to not have another menu line. Is overkill. |
126 |
|
[ ] Document GIT_TRACE=1 in the hints? |
|
127 |
516 |
[ ] If a repo is empty, should I show "Tree" menu?! |
[ ] If a repo is empty, should I show "Tree" menu?! |
128 |
517 |
Or at least, do not show an error! |
Or at least, do not show an error! |
129 |
518 |
[ ] Why do I not block the receiving of the commits in 'pre-receive' hook?! |
[ ] Why do I not block the receiving of the commits in 'pre-receive' hook?! |
|
145 |
534 |
[ ] html5: new types: http://html5doctor.com/html5-forms-input-types/ |
[ ] html5: new types: http://html5doctor.com/html5-forms-input-types/ |
146 |
535 |
[ ] WebAssembly: run rocketgit in a browser! |
[ ] WebAssembly: run rocketgit in a browser! |
147 |
536 |
[ ] Rate limit rg.com (both connlimit and x) |
[ ] Rate limit rg.com (both connlimit and x) |
148 |
|
[ ] ETag must not contain the inode (per vhost) |
|
149 |
|
Apache goes with a sane default. |
|
150 |
537 |
[ ] postgres: activate log_temp_files and log_lock_waits |
[ ] postgres: activate log_temp_files and log_lock_waits |
151 |
538 |
[ ] Limit the size of files at commit (in the rights section) |
[ ] Limit the size of files at commit (in the rights section) |
152 |
539 |
[ ] Investigate X-Content-Type-Options: "nosniff" |
[ ] Investigate X-Content-Type-Options: "nosniff" |
|
173 |
560 |
[ ] https://liberapay.com/ |
[ ] https://liberapay.com/ |
174 |
561 |
[ ] https://gratipay.com/ |
[ ] https://gratipay.com/ |
175 |
562 |
[ ] https://www.bountysource.com/ |
[ ] https://www.bountysource.com/ |
176 |
|
[ ] https://www.bountysource.com/ |
|
177 |
563 |
[ ] http://breachattack.com/ |
[ ] http://breachattack.com/ |
178 |
564 |
Investigate the solution to sign[/encrypt] secrets and regenerate them |
Investigate the solution to sign[/encrypt] secrets and regenerate them |
179 |
565 |
also to not store them in the database! I think the problem was the |
also to not store them in the database! I think the problem was the |
|
213 |
599 |
[ ] For API keys (maybe others), "Last IP" may be the IP who added the key. |
[ ] For API keys (maybe others), "Last IP" may be the IP who added the key. |
214 |
600 |
Or add an "Upload IP" field. |
Or add an "Upload IP" field. |
215 |
601 |
[ ] Add NoNewPrivileges to rocketgit-fpm service? |
[ ] Add NoNewPrivileges to rocketgit-fpm service? |
216 |
|
[ ] When I start the virtual machine, can I connect to console tu run the build |
|
|
602 |
|
[ ] When I start the virtual machine, can I connect to console to run the build |
217 |
603 |
script instead connecting by other means? To not have to modify |
script instead connecting by other means? To not have to modify |
218 |
604 |
the image... |
the image... |
219 |
|
[ ] Resize root partition to gain space and resize after boot. |
|
220 |
605 |
[ ] Add instructions to resize the base image: |
[ ] Add instructions to resize the base image: |
221 |
606 |
qemu-img resize Fedora-$TYPE-armhfp-25-1.3-sda.raw +10G |
qemu-img resize Fedora-$TYPE-armhfp-25-1.3-sda.raw +10G |
222 |
607 |
Do not forget about the filesystem! |
Do not forget about the filesystem! |
|
226 |
611 |
Add hints on how to do it. |
Add hints on how to do it. |
227 |
612 |
[ ] LOW: Generate an internal CA, allow clients to download certificates |
[ ] LOW: Generate an internal CA, allow clients to download certificates |
228 |
613 |
generated by this CA and verify them, to be able to act like ssh. |
generated by this CA and verify them, to be able to act like ssh. |
|
614 |
|
[ ] LOW: act as a CA and allow users to download certificates so we can use |
|
615 |
|
http as ssh? |
229 |
616 |
[ ] Low: add CURLOPT_PINNEDPUBLICKEY for webhooks. |
[ ] Low: add CURLOPT_PINNEDPUBLICKEY for webhooks. |
230 |
617 |
[ ] Add login token for http authentication! |
[ ] Add login token for http authentication! |
231 |
618 |
[ ] Make sure ETag is activated. |
[ ] Make sure ETag is activated. |
232 |
619 |
[ ] Add a hint on how to delete all files in a repository. |
[ ] Add a hint on how to delete all files in a repository. |
233 |
620 |
[ ] patreon.com? |
[ ] patreon.com? |
234 |
621 |
[ ] Add U2F support (see U2F Zero for free software/hardware) |
[ ] Add U2F support (see U2F Zero for free software/hardware) |
235 |
|
[ ] LOW: act as a CA and allow users to download certificates so wwe can use |
|
236 |
|
http as ssh? |
|
237 |
622 |
[ ] wh: add possibility to add public variables (values is public) or |
[ ] wh: add possibility to add public variables (values is public) or |
238 |
623 |
private variables (value cannot be retrieved) which will be provided |
private variables (value cannot be retrieved) which will be provided |
239 |
624 |
inside hook. How it applies to CI? |
inside hook. How it applies to CI? |
|
243 |
628 |
Ah, it is the owner! |
Ah, it is the owner! |
244 |
629 |
[ ] LOW: Allow build image to be persistent. |
[ ] LOW: Allow build image to be persistent. |
245 |
630 |
[ ] Deleting an account will not delete all stuff related (user_remove) |
[ ] Deleting an account will not delete all stuff related (user_remove) |
246 |
|
[ ] add to rg somrthing like: https://letsencrypt.org/become-a-sponsor/ |
|
|
631 |
|
[ ] add to rg something like: https://letsencrypt.org/become-a-sponsor/ |
247 |
632 |
[ ] wh: add support for OpenWhisk, similar with Amazon's Lambda |
[ ] wh: add support for OpenWhisk, similar with Amazon's Lambda |
248 |
633 |
[ ] On contributions page, as a way to help: recommend crowdfunding organzations. |
[ ] On contributions page, as a way to help: recommend crowdfunding organzations. |
249 |
634 |
[ ] SSH: the ratelimit may block some users? |
[ ] SSH: the ratelimit may block some users? |
|
272 |
657 |
[ ] test: do a test for rg_authorize command: upload a key and check by fp |
[ ] test: do a test for rg_authorize command: upload a key and check by fp |
273 |
658 |
[ ] test: add one for SSH AuthorizedKeysCommand |
[ ] test: add one for SSH AuthorizedKeysCommand |
274 |
659 |
[ ] LOW: add fuzzers for checking code. |
[ ] LOW: add fuzzers for checking code. |
275 |
|
[ ] Put password above e-mail, maybe this will fix the problem with user/pass |
|
276 |
|
caching. |
|
277 |
|
[ ] Use skipfish /w3af/etc. for security scanning |
|
|
660 |
|
[ ] Use skipfish/w3af/etc. for security scanning |
278 |
661 |
[ ] LOW: investigate https://aws.amazon.com/codepipeline/ |
[ ] LOW: investigate https://aws.amazon.com/codepipeline/ |
279 |
662 |
[ ] wh: start an ec2 machine |
[ ] wh: start an ec2 machine |
280 |
663 |
[ ] Discover: do not show repos which have no commit and no bug? |
[ ] Discover: do not show repos which have no commit and no bug? |
281 |
|
[ ] apache: configure it to not stat every path component! |
|
|
664 |
|
[ ] web server: configure it to not stat every path component! |
282 |
665 |
[ ] First page: link to the Changelog? |
[ ] First page: link to the Changelog? |
283 |
666 |
[ ] Compare: supported distributions |
[ ] Compare: supported distributions |
284 |
667 |
[ ] What happends when an environment is not available anymore? |
[ ] What happends when an environment is not available anymore? |
|
316 |
699 |
[ ] Debian: on reconfigure - add admin account? |
[ ] Debian: on reconfigure - add admin account? |
317 |
700 |
[ ] Investivate gc.*, repack.* etc. configuration. |
[ ] Investivate gc.*, repack.* etc. configuration. |
318 |
701 |
[ ] Use .mailmap when building stats? |
[ ] Use .mailmap when building stats? |
319 |
|
[ ] Before start a builing, check if it was already built. |
|
|
702 |
|
[ ] Before start a build, check if it was already built. |
320 |
703 |
Think about a fast forward. |
Think about a fast forward. |
321 |
704 |
[ ] API: When loading info about a user, do we need to show the e-mail? |
[ ] API: When loading info about a user, do we need to show the e-mail? |
322 |
705 |
[ ] API: Seems I get: |
[ ] API: Seems I get: |
|
359 |
742 |
[ ] Use 'guestfish --ro -a a.img -i'. What for? |
[ ] Use 'guestfish --ro -a a.img -i'. What for? |
360 |
743 |
[ ] Add 'X-Content-Type-Options: nosniff' for raw responses. |
[ ] Add 'X-Content-Type-Options: nosniff' for raw responses. |
361 |
744 |
[ ] Check 'X-XSS-Protection: 1; mode=block' |
[ ] Check 'X-XSS-Protection: 1; mode=block' |
362 |
|
[ ] Better explain why world needs another git hosting repo. |
|
|
745 |
|
[ ] Better explain why world needs another git hosting software. |
363 |
746 |
[ ] Features: I did not explain what Affero means! Only GPL. |
[ ] Features: I did not explain what Affero means! Only GPL. |
364 |
747 |
[ ] fpm: provide a classic startup file. |
[ ] fpm: provide a classic startup file. |
365 |
748 |
[ ] Some errors are like: 'cannot insert/update'. Are not very helpful! |
[ ] Some errors are like: 'cannot insert/update'. Are not very helpful! |
|
... |
... |
to add a worker? Also, no hint is presented. |
373 |
756 |
I do not think so... Should we have a write ahead log: |
I do not think so... Should we have a write ahead log: |
374 |
757 |
something like we inform the cache that we need to clean an entry |
something like we inform the cache that we need to clean an entry |
375 |
758 |
it the connection is broken. |
it the connection is broken. |
376 |
|
[ ] UTF8 with the databse, please check. |
|
377 |
|
[ ] main page: add a new way to ear money: add sponsort, directly in the source |
|
|
759 |
|
[ ] UTF8 with the database, please check. |
|
760 |
|
[ ] main page: add a new way to earn money: add sponsors, directly in the source |
378 |
761 |
to be shown on every deployed rocketgit instalation. |
to be shown on every deployed rocketgit instalation. |
379 |
762 |
We can use bidding for the order. |
We can use bidding for the order. |
380 |
763 |
[ ] Investigate socket activation for fpm? Cache? Events? |
[ ] Investigate socket activation for fpm? Cache? Events? |
|
... |
... |
to add a worker? Also, no hint is presented. |
515 |
898 |
How it will work?! By default, all rights. |
How it will work?! By default, all rights. |
516 |
899 |
Use case: allow a key only to push on some repos (regex) |
Use case: allow a key only to push on some repos (regex) |
517 |
900 |
Use case: allow a key to only access repo APIs. |
Use case: allow a key to only access repo APIs. |
518 |
|
[ ] Scan SSH/API keys and notify user whey were used too long ago, and ask |
|
|
901 |
|
[ ] Scan SSH/API keys and notify user when they were used too long ago, and ask |
519 |
902 |
the user to remove them? |
the user to remove them? |
520 |
903 |
[ ] From time to time, regenerate the passwords with other salt to protect |
[ ] From time to time, regenerate the passwords with other salt to protect |
521 |
904 |
against stolen db and brute force attacks. |
against stolen db and brute force attacks. |
|
... |
... |
to add a worker? Also, no hint is presented. |
527 |
910 |
logs. |
logs. |
528 |
911 |
[ ] Add an API layer to be able to use other git hosting scripts to connect to me |
[ ] Add an API layer to be able to use other git hosting scripts to connect to me |
529 |
912 |
[ ] Sign some contract with Nitrokey.com to provide keys to the users. |
[ ] Sign some contract with Nitrokey.com to provide keys to the users. |
530 |
|
[ ] build: allow user to specify some packages to be installed first? |
|
531 |
913 |
[ ] Destroy storage for 'build' machines |
[ ] Destroy storage for 'build' machines |
532 |
914 |
[ ] Add a new right: "allow pushes only if they are signed". |
[ ] Add a new right: "allow pushes only if they are signed". |
533 |
|
As with ss keys, a user may want to add public gpg keys to a list |
|
|
915 |
|
As with ssh keys, a user may want to add public gpg keys to a list |
534 |
916 |
that is allowed to push. Take care: you can sign tags but also |
that is allowed to push. Take care: you can sign tags but also |
535 |
917 |
commits. |
commits. |
536 |
918 |
[ ] Slack: push also the commit message. |
[ ] Slack: push also the commit message. |
|
... |
... |
to add a worker? Also, no hint is presented. |
648 |
1030 |
[ ] LOW: mr: notify the owner of the pull request (if not anonymous)? |
[ ] LOW: mr: notify the owner of the pull request (if not anonymous)? |
649 |
1031 |
[ ] LOW: when destroying a repo, destroy the cache by path (git caches by path) |
[ ] LOW: when destroying a repo, destroy the cache by path (git caches by path) |
650 |
1032 |
[ ] LOW: /usr/share/rocketgit/root/themes/default//usr/share/rocketgit/root/themes/default/hints/list/header.html |
[ ] LOW: /usr/share/rocketgit/root/themes/default//usr/share/rocketgit/root/themes/default/hints/list/header.html |
651 |
|
[ ] LOW: mr: private pull requests? |
|
652 |
|
[ ] LOW: mr: get rid of namespaces? |
|
|
1033 |
|
[ ] LOW: mr: get rid of namespaces? overlayfs? |
653 |
1034 |
[ ] LOW: mr: add possibility to reject a pull request. |
[ ] LOW: mr: add possibility to reject a pull request. |
654 |
1035 |
[ ] LOW: mr: add the right to reject pull requests. |
[ ] LOW: mr: add the right to reject pull requests. |
655 |
1036 |
[ ] LOW: mr: allow adding comments for pull requests. |
[ ] LOW: mr: allow adding comments for pull requests. |
|
... |
... |
to add a worker? Also, no hint is presented. |
657 |
1038 |
[ ] LOW: mr: allow the anonymous users to delete a pull request by providing |
[ ] LOW: mr: allow the anonymous users to delete a pull request by providing |
658 |
1039 |
a link. |
a link. |
659 |
1040 |
[ ] LOW: mr: allow the owner to remove a pull request. |
[ ] LOW: mr: allow the owner to remove a pull request. |
660 |
|
[ ] LOW: mr: Use rg_git_request_pull to generate a pull request from a onw repo. |
|
|
1041 |
|
[ ] LOW: mr: Use rg_git_request_pull to generate a pull request from an own repo. |
661 |
1042 |
Example: git request-pull master~4 git://localhost/user/catab/testpull |
Example: git request-pull master~4 git://localhost/user/catab/testpull |
662 |
1043 |
We must present a list of commits, so the user can choose 'start' and |
We must present a list of commits, so the user can choose 'start' and |
663 |
1044 |
'end'. |
'end'. |
|
... |
... |
to add a worker? Also, no hint is presented. |
678 |
1059 |
[ ] LOW: mr: commits must be isolated in div islands with some background |
[ ] LOW: mr: commits must be isolated in div islands with some background |
679 |
1060 |
[ ] LOW: mr: maybe files should be listen on the right of the commit info? |
[ ] LOW: mr: maybe files should be listen on the right of the commit info? |
680 |
1061 |
[ ] LOW: mr: Commits must be indented somehow. |
[ ] LOW: mr: Commits must be indented somehow. |
681 |
|
[ ] LOW: mr: between diff and "Commit xxx" the is no space! |
|
|
1062 |
|
[ ] LOW: mr: between diff and "Commit xxx" there is no space! |
682 |
1063 |
[ ] LOW: In log/line.html, subject should also be a link to the commit |
[ ] LOW: In log/line.html, subject should also be a link to the commit |
683 |
1064 |
[ ] LOW: mr: allow user to resolve conflicts online? |
[ ] LOW: mr: allow user to resolve conflicts online? |
684 |
1065 |
[ ] LOW: mr: error messages must still show the merge information. |
[ ] LOW: mr: error messages must still show the merge information. |
|
... |
... |
them after processing is done. |
2020 |
2401 |
[ ] Check double slashes in URLs. |
[ ] Check double slashes in URLs. |
2021 |
2402 |
[ ] Automatically create user on anonymous push? |
[ ] Automatically create user on anonymous push? |
2022 |
2403 |
[ ] I am not sure I can reload xinetd and httpd from spec file |
[ ] I am not sure I can reload xinetd and httpd from spec file |
2023 |
|
[ ] Check SELinux context on /var/lib/rocketgit |
|
2024 |
2404 |
[ ] admin: "Lock all accounts" and "Reset password for all accounts and send mail". |
[ ] admin: "Lock all accounts" and "Reset password for all accounts and send mail". |
2025 |
2405 |
[ ] Get memory statistics from /proc. |
[ ] Get memory statistics from /proc. |
2026 |
2406 |
[ ] Add support for refs/notes/ pushes. |
[ ] Add support for refs/notes/ pushes. |
|
... |
... |
them after processing is done. |
2028 |
2408 |
[ ] Ask password when doing any critical change of the account and send mail. |
[ ] Ask password when doing any critical change of the account and send mail. |
2029 |
2409 |
[ ] Add a possibility (link shown in push message) to delete/update/etc. the |
[ ] Add a possibility (link shown in push message) to delete/update/etc. the |
2030 |
2410 |
merge request. |
merge request. |
2031 |
|
[ ] Allow a nonstandard port for web. |
|
2032 |
2411 |
[ ] Put form error messages next to the label. |
[ ] Put form error messages next to the label. |
2033 |
2412 |
[ ] favicon.ico is not in theme! Should we put it in HTML? |
[ ] favicon.ico is not in theme! Should we put it in HTML? |
2034 |
2413 |
[ ] Create unit testing for all functions. |
[ ] Create unit testing for all functions. |
2035 |
2414 |
[ ] Test error code for rg_sql_query. |
[ ] Test error code for rg_sql_query. |
2036 |
2415 |
[ ] Log $ret['errmsg'] for rg_exec |
[ ] Log $ret['errmsg'] for rg_exec |
2037 |
2416 |
[ ] Audit code to replace parts with rg_internal_error. |
[ ] Audit code to replace parts with rg_internal_error. |
2038 |
|
[ ] Allow SSH keys per repository (only)? |
|
|
2417 |
|
[ ] Allow SSH keys per repository (only)? regex? |
2039 |
2418 |
[ ] Allow remote 'gc' of a repo, besides an automatic one. |
[ ] Allow remote 'gc' of a repo, besides an automatic one. |
2040 |
2419 |
[ ] Take care of caching of passwords. Maybe allow a purge of a file from browser? |
[ ] Take care of caching of passwords. Maybe allow a purge of a file from browser? |
2041 |
2420 |
[ ] "Lock" button to temporary block access to repository. |
[ ] "Lock" button to temporary block access to repository. |
2042 |
2421 |
Only owner will have access. |
Only owner will have access. |
2043 |
2422 |
We may add also a text that will be output to clients. |
We may add also a text that will be output to clients. |
|
2423 |
|
Add to 'compare'. |
2044 |
2424 |
[ ] List changes introduced by a merge: git diff-tree --always [--cc] -m -p f7d5b5770f4c6b5a124dad6358bed310d56bf909 |
[ ] List changes introduced by a merge: git diff-tree --always [--cc] -m -p f7d5b5770f4c6b5a124dad6358bed310d56bf909 |
2045 |
2425 |
[ ] Check pack-protocol.txt! |
[ ] Check pack-protocol.txt! |
2046 |
2426 |
[ ] When push is executed with success, show a nice message from RocketGit. |
[ ] When push is executed with success, show a nice message from RocketGit. |
|
... |
... |
them after processing is done. |
2083 |
2463 |
hook? Or update is the best place? |
hook? Or update is the best place? |
2084 |
2464 |
[ ] Limit number of commits per push. |
[ ] Limit number of commits per push. |
2085 |
2465 |
[ ] RSS |
[ ] RSS |
2086 |
|
[ ] Smart HTTP transport |
|
2087 |
2466 |
[ ] Move forget pass token into users table. |
[ ] Move forget pass token into users table. |
2088 |
2467 |
[ ] Audit all error messages to not propagate useful info to an attacker. |
[ ] Audit all error messages to not propagate useful info to an attacker. |
2089 |
2468 |
Split in two error messages: one for logs and one for user. |
Split in two error messages: one for logs and one for user. |
|
... |
... |
them after processing is done. |
2097 |
2476 |
[ ] Check SELinux MLS |
[ ] Check SELinux MLS |
2098 |
2477 |
[ ] Deal with empty repositories (rg_git_ls_tree etc.). |
[ ] Deal with empty repositories (rg_git_ls_tree etc.). |
2099 |
2478 |
[ ] Show age of an user/org/repo. Example: 1 year, 3 months, 4 days. |
[ ] Show age of an user/org/repo. Example: 1 year, 3 months, 4 days. |
2100 |
|
[ ] The rewrite engine should pass a single op for user and for org, but with |
|
2101 |
|
para org=0 or 1. |
|
2102 |
|
This is to have the same page for both types of users. |
|
2103 |
2479 |
[ ] From: http://lwn.net/Articles/460376/ |
[ ] From: http://lwn.net/Articles/460376/ |
2104 |
2480 |
I can confirm that shortcomings with Gitorious' ACL systems were |
I can confirm that shortcomings with Gitorious' ACL systems were |
2105 |
2481 |
definitely one of the reasons we ended up deciding against it -- |
definitely one of the reasons we ended up deciding against it -- |
File inc/ldap.inc.php added (mode: 100644) (index 0000000..39aa7ed) |
|
1 |
|
<?php |
|
2 |
|
require_once($INC . '/sql.inc.php'); |
|
3 |
|
require_once($INC . '/state.inc.php'); |
|
4 |
|
require_once($INC . '/prof.inc.php'); |
|
5 |
|
require_once($INC . '/cache.inc.php'); |
|
6 |
|
require_once($INC . '/plan.inc.php'); |
|
7 |
|
require_once($INC . '/ldap_core.inc.php'); |
|
8 |
|
require_once($INC . '/ldap_sync.inc.php'); |
|
9 |
|
|
|
10 |
|
|
|
11 |
|
$rg_ldap_error = ''; |
|
12 |
|
|
|
13 |
|
function rg_ldap_set_error($str) |
|
14 |
|
{ |
|
15 |
|
global $rg_ldap_error; |
|
16 |
|
$rg_ldap_error = $str; |
|
17 |
|
rg_log($str); |
|
18 |
|
} |
|
19 |
|
|
|
20 |
|
function rg_ldap_error() |
|
21 |
|
{ |
|
22 |
|
global $rg_ldap_error; |
|
23 |
|
return $rg_ldap_error; |
|
24 |
|
} |
|
25 |
|
|
|
26 |
|
/* |
|
27 |
|
* Some cosmetics applied to a LDAP server (one row) |
|
28 |
|
*/ |
|
29 |
|
function rg_ldap_cosmetic_row($db, &$row) |
|
30 |
|
{ |
|
31 |
|
if (isset($row['itime'])) |
|
32 |
|
$row['itime_nice'] = gmdate('Y-m-d H:i', $row['itime']); |
|
33 |
|
|
|
34 |
|
$pi = rg_plan_info($db, $row['plan_id']); |
|
35 |
|
if ($pi['exists'] == 1) |
|
36 |
|
$row['plan'] = $pi['name']; |
|
37 |
|
else |
|
38 |
|
$row['plan'] = 'Error!'; |
|
39 |
|
} |
|
40 |
|
|
|
41 |
|
/* |
|
42 |
|
* Some cosmetics applied to a LDAP server (array) |
|
43 |
|
*/ |
|
44 |
|
function rg_ldap_cosmetic($db, &$a) |
|
45 |
|
{ |
|
46 |
|
foreach ($a as $k => &$i) |
|
47 |
|
rg_ldap_cosmetic_row($db, $i); |
|
48 |
|
} |
|
49 |
|
|
|
50 |
|
/* |
|
51 |
|
* Sorting the LDAP servers |
|
52 |
|
*/ |
|
53 |
|
function rg_ldap_sort_helper($a, $b) |
|
54 |
|
{ |
|
55 |
|
if ($a['prio'] < $b['prio']) |
|
56 |
|
return -1; |
|
57 |
|
|
|
58 |
|
if ($a['prio'] > $b['prio']) |
|
59 |
|
return 1; |
|
60 |
|
|
|
61 |
|
return strcmp($a['name'], $b['name']); |
|
62 |
|
} |
|
63 |
|
|
|
64 |
|
/* |
|
65 |
|
* Returns a list of LDAP servers |
|
66 |
|
*/ |
|
67 |
|
function rg_ldap_list($db) |
|
68 |
|
{ |
|
69 |
|
rg_prof_start('ldap_list'); |
|
70 |
|
rg_log_enter('ldap_list'); |
|
71 |
|
|
|
72 |
|
$ret = array('ok' => 0, 'list' => array()); |
|
73 |
|
while (1) { |
|
74 |
|
$key = 'ldap'; |
|
75 |
|
$r = rg_cache_get($key); |
|
76 |
|
if (($r !== FALSE) && isset($r['LIST_LOADED'])) { |
|
77 |
|
$ret['list'] = $r['list']; |
|
78 |
|
$ret['ok'] = 1; |
|
79 |
|
break; |
|
80 |
|
} |
|
81 |
|
|
|
82 |
|
$params = array(); |
|
83 |
|
$sql = 'SELECT * FROM ldap_servers ORDER BY prio, name'; |
|
84 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
85 |
|
if ($res === FALSE) { |
|
86 |
|
rg_ldap_set_error('cannot load data'); |
|
87 |
|
break; |
|
88 |
|
} |
|
89 |
|
|
|
90 |
|
while (($row = rg_sql_fetch_array($res))) { |
|
91 |
|
$id = $row['id']; |
|
92 |
|
$ret['list'][$id] = $row; |
|
93 |
|
} |
|
94 |
|
rg_sql_free_result($res); |
|
95 |
|
|
|
96 |
|
$a = array('LIST_LOADED' => 1, 'list' => $ret['list']); |
|
97 |
|
rg_cache_merge($key, $a, RG_SOCKET_NO_WAIT); |
|
98 |
|
$ret['ok'] = 1; |
|
99 |
|
break; |
|
100 |
|
} |
|
101 |
|
uasort($ret['list'], 'rg_ldap_sort_helper'); |
|
102 |
|
|
|
103 |
|
rg_log_exit(); |
|
104 |
|
rg_prof_end('ldap_list'); |
|
105 |
|
return $ret; |
|
106 |
|
} |
|
107 |
|
|
|
108 |
|
/* |
|
109 |
|
* Adds/edits a ldap_server |
|
110 |
|
*/ |
|
111 |
|
function rg_ldap_add($db, $who, $data) |
|
112 |
|
{ |
|
113 |
|
rg_prof_start('ldap_add'); |
|
114 |
|
rg_log_enter('ldap_add'); |
|
115 |
|
|
|
116 |
|
$ret = array('ok' => 0); |
|
117 |
|
while (1) { |
|
118 |
|
$data['who'] = $who; |
|
119 |
|
$data['itime'] = time(); |
|
120 |
|
$params = $data; |
|
121 |
|
|
|
122 |
|
if ($data['id'] == 0) { |
|
123 |
|
$sql = 'INSERT INTO ldap_servers (itime, who, name' |
|
124 |
|
. ', url, bind_dn, bind_pass, user_base' |
|
125 |
|
. ', uid_attr, filter, group_base, group_attr' |
|
126 |
|
. ', group_filter, admin_group, ca_cert' |
|
127 |
|
. ', prio, session_time)' |
|
128 |
|
. ' VALUES (@@itime@@, @@who@@, @@name@@' |
|
129 |
|
. ', @@url@@, @@bind_dn@@, @@bind_pass@@' |
|
130 |
|
. ', @@user_base@@, @@uid_attr@@, @@filter@@' |
|
131 |
|
. ', @@group_base@@, @@group_attr@@' |
|
132 |
|
. ', @@group_filter@@, @@admin_group@@' |
|
133 |
|
. ', @@ca_cert@@, @@prio@@, @@session_time@@)' |
|
134 |
|
. ' RETURNING id'; |
|
135 |
|
} else { |
|
136 |
|
$sql = 'UPDATE ldap_servers' |
|
137 |
|
. ' SET itime = @@itime@@' |
|
138 |
|
. ', who = @@who@@' |
|
139 |
|
. ', name = @@name@@' |
|
140 |
|
. ', url = @@url@@' |
|
141 |
|
. ', bind_dn = @@bind_dn@@' |
|
142 |
|
. ', bind_pass = @@bind_pass@@' |
|
143 |
|
. ', user_base = @@user_base@@' |
|
144 |
|
. ', uid_attr = @@uid_attr@@' |
|
145 |
|
. ', filter = @@filter@@' |
|
146 |
|
. ', group_base = @@group_base@@' |
|
147 |
|
. ', group_attr = @@group_attr@@' |
|
148 |
|
. ', group_filter = @@group_filter@@' |
|
149 |
|
. ', admin_group = @@admin_group@@' |
|
150 |
|
. ', ca_cert = @@ca_cert@@' |
|
151 |
|
. ', prio = @@prio@@' |
|
152 |
|
. ', session_time = @@session_time@@' |
|
153 |
|
. ' WHERE id = @@id@@'; |
|
154 |
|
} |
|
155 |
|
|
|
156 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
157 |
|
if ($res === FALSE) { |
|
158 |
|
rg_ldap_set_error('cannot insert/update data'); |
|
159 |
|
break; |
|
160 |
|
} |
|
161 |
|
if ($data['id'] == 0) |
|
162 |
|
$row = rg_sql_fetch_array($res); |
|
163 |
|
rg_sql_free_result($res); |
|
164 |
|
|
|
165 |
|
if ($data['id'] == 0) |
|
166 |
|
$data['id'] = $row['id']; |
|
167 |
|
$key = 'ldap' . '::' . 'list' |
|
168 |
|
. '::' . $data['id']; |
|
169 |
|
rg_cache_merge($key, $data, RG_SOCKET_NO_WAIT); |
|
170 |
|
|
|
171 |
|
$ret['ok'] = 1; |
|
172 |
|
break; |
|
173 |
|
} |
|
174 |
|
|
|
175 |
|
rg_log_exit(); |
|
176 |
|
rg_prof_end('ldap_add'); |
|
177 |
|
return $ret; |
|
178 |
|
} |
|
179 |
|
|
|
180 |
|
/* |
|
181 |
|
* Removes a list of ldap_servers |
|
182 |
|
*/ |
|
183 |
|
function rg_ldap_remove($db, $list) |
|
184 |
|
{ |
|
185 |
|
rg_prof_start('ldap_remove'); |
|
186 |
|
rg_log_enter('ldap_remove'); |
|
187 |
|
|
|
188 |
|
$ret = array('ok' => 0); |
|
189 |
|
while (1) { |
|
190 |
|
if (empty($list)) { |
|
191 |
|
rg_ldap_set_error('you did not select anything'); |
|
192 |
|
break; |
|
193 |
|
} |
|
194 |
|
|
|
195 |
|
$my_list = array(); |
|
196 |
|
foreach ($list as $id => $junk) |
|
197 |
|
$my_list[] = sprintf('%u', $id); |
|
198 |
|
|
|
199 |
|
$params = array(); |
|
200 |
|
$sql_list = implode(', ', $my_list); |
|
201 |
|
|
|
202 |
|
$sql = 'DELETE FROM ldap_cache' |
|
203 |
|
. ' WHERE server_id IN (' . $sql_list . ')'; |
|
204 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
205 |
|
if ($res === FALSE) { |
|
206 |
|
rg_ldap_set_error('cannot remove data from db cache'); |
|
207 |
|
break; |
|
208 |
|
} |
|
209 |
|
rg_sql_free_result($res); |
|
210 |
|
|
|
211 |
|
$sql = 'DELETE FROM ldap_servers' |
|
212 |
|
. ' WHERE id IN (' . $sql_list . ')'; |
|
213 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
214 |
|
if ($res === FALSE) { |
|
215 |
|
rg_ldap_set_error('cannot remove server from db'); |
|
216 |
|
break; |
|
217 |
|
} |
|
218 |
|
rg_sql_free_result($res); |
|
219 |
|
|
|
220 |
|
foreach ($my_list as $junk => $id) { |
|
221 |
|
$key = 'ldap' . '::' . 'list' . '::' . $id; |
|
222 |
|
rg_cache_unset($key, RG_SOCKET_NO_WAIT); |
|
223 |
|
} |
|
224 |
|
|
|
225 |
|
$ret['ok'] = 1; |
|
226 |
|
break; |
|
227 |
|
} |
|
228 |
|
|
|
229 |
|
rg_log_exit(); |
|
230 |
|
rg_prof_end('ldap_remove'); |
|
231 |
|
return $ret; |
|
232 |
|
} |
|
233 |
|
|
|
234 |
|
/* |
|
235 |
|
* Helper function for ldap_login |
|
236 |
|
*/ |
|
237 |
|
function rg_ldap_a_and_si_to_a_ui(&$ui, &$a, $si) |
|
238 |
|
{ |
|
239 |
|
$a['username'] = $a['ldap_uid']; |
|
240 |
|
$a['realname'] = $a['cn'] . ' (' . $a['gn'] . ' ' . $a['sn'] . ')'; |
|
241 |
|
|
|
242 |
|
$ui['session_time'] = $si['session_time']; |
|
243 |
|
$ui['plan_id'] = $si['plan_id']; |
|
244 |
|
$ui['realname'] = $a['realname']; |
|
245 |
|
$ui['username'] = $a['username']; |
|
246 |
|
$ui['email'] = $a['mail']; |
|
247 |
|
$ui['pass'] = $a['password']; |
|
248 |
|
$ui['pass2'] = $a['password']; |
|
249 |
|
|
|
250 |
|
$ui['confirm_token'] = ''; |
|
251 |
|
$ui['confirmed'] = 1; |
|
252 |
|
$ui['exists'] = 1; |
|
253 |
|
$ui['deleted'] = 0; |
|
254 |
|
$ui['suspended'] = 0; |
|
255 |
|
} |
|
256 |
|
|
|
257 |
|
/* |
|
258 |
|
* Authentication function used by rg_user_login_by_user_pass |
|
259 |
|
*/ |
|
260 |
|
rg_register_login_function( |
|
261 |
|
array( |
|
262 |
|
'login' => 'rg_ldap_login', |
|
263 |
|
'post_login' => 'rg_ldap_login_post' |
|
264 |
|
) |
|
265 |
|
); |
|
266 |
|
function rg_ldap_login($db, $user, $pass, &$ui) |
|
267 |
|
{ |
|
268 |
|
global $rg_session_time; |
|
269 |
|
|
|
270 |
|
rg_log_enter('ldap_login'); |
|
271 |
|
|
|
272 |
|
$ret = array(); |
|
273 |
|
$ret['ok'] = 0; |
|
274 |
|
$found = FALSE; |
|
275 |
|
while (1) { |
|
276 |
|
$sl = rg_ldap_list($db); |
|
277 |
|
if ($sl['ok'] !== 1) { |
|
278 |
|
$ret['errmsg'] = $sl['errmsg']; |
|
279 |
|
break; |
|
280 |
|
} |
|
281 |
|
|
|
282 |
|
// First, we try to find the user in cache |
|
283 |
|
// TODO: make the cache to expire |
|
284 |
|
$r = rg_ldap_sync_get_cache($db, $user); |
|
285 |
|
if ($r['ok'] === 1) { |
|
286 |
|
foreach ($r['list'] as $a) { |
|
287 |
|
rg_log_ml('DEBUG: cache: ' . print_r($a, TRUE)); |
|
288 |
|
// TODO: test if the entry is expired |
|
289 |
|
// TODO: encrypt password! |
|
290 |
|
if (strcmp($a['password'], $pass) != 0) { |
|
291 |
|
rg_log('DEBUG: passwords do not match [' |
|
292 |
|
. $a['password'] . '] [' . $pass . ']'); |
|
293 |
|
continue; |
|
294 |
|
} |
|
295 |
|
|
|
296 |
|
$server_id = $a['server_id']; |
|
297 |
|
if (!isset($sl['list'][$server_id])) { |
|
298 |
|
rg_internal_error('We found a stall' |
|
299 |
|
. ' ldap server_id in cache!'); |
|
300 |
|
continue; |
|
301 |
|
} |
|
302 |
|
|
|
303 |
|
rg_log('DEBUG: Found a good cache entry!'); |
|
304 |
|
rg_ldap_a_and_si_to_a_ui($ui, $a, |
|
305 |
|
$sl['list'][$server_id]); |
|
306 |
|
|
|
307 |
|
if ($a['uid'] > 0) |
|
308 |
|
$ui['uid'] = $a['uid']; |
|
309 |
|
|
|
310 |
|
$ret['post'] = $a; |
|
311 |
|
$ret['ok'] = 1; |
|
312 |
|
break; |
|
313 |
|
} |
|
314 |
|
if ($ret['ok'] == 1) |
|
315 |
|
break; |
|
316 |
|
} |
|
317 |
|
|
|
318 |
|
$euser = ldap_escape($user, NULL, LDAP_ESCAPE_FILTER); |
|
319 |
|
|
|
320 |
|
foreach ($sl['list'] as $si) { |
|
321 |
|
//rg_log_ml('ldap server info: ' . print_r($si, TRUE)); |
|
322 |
|
|
|
323 |
|
$r = rg_ldap_core_connect($si['url']); |
|
324 |
|
if ($r['ok'] !== 1) { |
|
325 |
|
rg_log('DEBUG: cannot connect: ' . $r['errmsg']); |
|
326 |
|
$ret['errmsg'] = $r['errmsg']; |
|
327 |
|
continue; |
|
328 |
|
} |
|
329 |
|
$con = $r['con']; |
|
330 |
|
rg_log('DEBUG: connected to ' . $si['url']); |
|
331 |
|
|
|
332 |
|
rg_log('DEBUG: binding as [' . $si['bind_dn'] . ']'); |
|
333 |
|
$r = rg_ldap_core_bind($con, $si['bind_dn'], |
|
334 |
|
$si['bind_pass']); |
|
335 |
|
if ($r['ok'] !== 1) { |
|
336 |
|
rg_log('DEBUG: cannot bind: ' . $r['errmsg']); |
|
337 |
|
$ret['errmsg'] = $r['errmsg']; |
|
338 |
|
continue; |
|
339 |
|
} |
|
340 |
|
rg_log('DEBUG: bind1 ok!'); |
|
341 |
|
|
|
342 |
|
// TODO: should I validate uid field - injection? |
|
343 |
|
$uid_attr = strtolower($si['uid_attr']); |
|
344 |
|
$filter = '(|' |
|
345 |
|
. '(mail=' . $euser . ')' |
|
346 |
|
. '(cn=' . $euser . ')' |
|
347 |
|
. '(' . $uid_attr . '=' . $euser . ')' |
|
348 |
|
. ')'; |
|
349 |
|
if (!empty($si['filter'])) |
|
350 |
|
$filter = '(&' . $filter |
|
351 |
|
. '(' . ldap_escape($si['filter'], NULL, LDAP_ESCAPE_FILTER) . '))'; |
|
352 |
|
rg_log('DEBUG: filter: ' . $filter); |
|
353 |
|
rg_log('DEBUG: base=' . $si['user_base']); |
|
354 |
|
|
|
355 |
|
$deref = LDAP_DEREF_NEVER; // TODO: this should be in $si |
|
356 |
|
$attr = array('cn', 'mail', 'entryUUID', 'memberOf', |
|
357 |
|
'mail', 'sn', 'givenName', 'objectClass', |
|
358 |
|
'uid', 'shadowExpire', 'uidNumber', 'gidNumber', |
|
359 |
|
$uid_attr); |
|
360 |
|
$r = rg_ldap_core_search($con, $si['user_base'], $filter, |
|
361 |
|
$attr, 0 /*attronly*/, 0 /*sizelimit*/, |
|
362 |
|
0 /*timelimit*/, $deref); |
|
363 |
|
if ($r['ok'] !== 1) { |
|
364 |
|
rg_log('DEBUG: cannot search: ' . $r['errmsg']); |
|
365 |
|
$ret['errmsg'] = $r['errmsg']; |
|
366 |
|
continue; |
|
367 |
|
} |
|
368 |
|
if (empty($r['data']) || !isset($r['data'][0])) { |
|
369 |
|
rg_log('DEBUG: cannot find data'); |
|
370 |
|
$ret['errmsg'] = 'user not found'; |
|
371 |
|
continue; |
|
372 |
|
} |
|
373 |
|
|
|
374 |
|
// Have to test here if we can bind with the user found |
|
375 |
|
// We may have more users, but we will select the first one |
|
376 |
|
$d = $r['data'][0]; |
|
377 |
|
rg_log('DEBUG: binding as [' . $d['dn'] . '] pass=' . $pass); |
|
378 |
|
$r = rg_ldap_core_bind($con, $d['dn'], $pass); |
|
379 |
|
if ($r['ok'] !== 1) { |
|
380 |
|
rg_log('DEBUG: cannot bind: ' . $r['errmsg']); |
|
381 |
|
$ret['errmsg'] = $r['errmsg']; |
|
382 |
|
continue; |
|
383 |
|
} |
|
384 |
|
rg_log('DEBUG: bind2 ok!'); |
|
385 |
|
|
|
386 |
|
unset($ret['errmsg']); |
|
387 |
|
$found = TRUE; |
|
388 |
|
break; |
|
389 |
|
} |
|
390 |
|
if (!$found) |
|
391 |
|
break; |
|
392 |
|
|
|
393 |
|
rg_log_ml('DEBUG: got data from LDAP: d=' . print_r($d, TRUE)); |
|
394 |
|
|
|
395 |
|
// $a will be the $ret['post'] |
|
396 |
|
// It will be used to test if an update into 'users' is needed. |
|
397 |
|
// Also, to insert into ldap_cache. |
|
398 |
|
$a = array(); |
|
399 |
|
$a['cn'] = isset($d['cn'][0]) ? $d['cn'][0] : ''; |
|
400 |
|
$a['gn'] = isset($d['givenname'][0]) ? $d['givenname'][0] : ''; |
|
401 |
|
$a['sn'] = isset($d['sn'][0]) ? $d['sn'][0] : ''; |
|
402 |
|
$a['shadow_expire'] = isset($d['shadowexpire'][0]) ? $d['mail'][0] : '99999'; |
|
403 |
|
$uid_attr = strtolower($si['uid_attr']); |
|
404 |
|
$a['ldap_uid'] = isset($d[$uid_attr][0]) ? $d[$uid_attr][0] : ''; |
|
405 |
|
$a['mail'] = isset($d['mail'][0]) ? $d['mail'][0] : ''; |
|
406 |
|
// TODO: really needed? I think not, we will use it in ldap_cache |
|
407 |
|
//$a['uid_number'] = isset($d['uidnumber'][0]) ? $d['mail'][0] : ''; |
|
408 |
|
$a['password'] = $pass; |
|
409 |
|
rg_log_ml('DEBUG: built a=' . print_r($a, TRUE)); |
|
410 |
|
|
|
411 |
|
rg_ldap_a_and_si_to_a_ui($ui, $a, $si); |
|
412 |
|
|
|
413 |
|
// TODO: what to do when the admin changes the plan_id per server? |
|
414 |
|
// I have to identify the users and change the plan. |
|
415 |
|
|
|
416 |
|
$ui['is_admin'] = 0; |
|
417 |
|
if (isset($d['memberof'])) { |
|
418 |
|
for ($j = 0; $j < $d['memberof']['count']; $j++) { |
|
419 |
|
//rg_log('DEBUG: comparing ' . $d['memberof'][$j] . ' with ' . $si['admin_group']); |
|
420 |
|
// TODO: Do I have to escape `? |
|
421 |
|
$r = @preg_match('`' . $si['admin_group'] . '`uD', $d['memberof'][$j]); |
|
422 |
|
if ($r === 1) { |
|
423 |
|
$ui['is_admin'] = 1; |
|
424 |
|
break; |
|
425 |
|
} |
|
426 |
|
} |
|
427 |
|
} |
|
428 |
|
|
|
429 |
|
$ui['suspended'] = $a['shadow_expire'] <= time() / 24 / 3600 ? 1 : 0; |
|
430 |
|
// TODO: With 99999 it will not compute right! |
|
431 |
|
$ui['expire'] = gmmktime(0, 0, 0, 1, ($a['shadow_expire'] + 24 * 3600 - 1) / 24 / 3600, 1970) - 1; |
|
432 |
|
|
|
433 |
|
$ui['ok'] = 1; |
|
434 |
|
|
|
435 |
|
rg_log_ml('DEBUG: ui: ' . print_r($ui, TRUE)); |
|
436 |
|
|
|
437 |
|
// Prepare these for 'login_post' function, to update the cache. |
|
438 |
|
$ret['post'] = $a; |
|
439 |
|
$ret['post']['uid'] = 0; |
|
440 |
|
$ret['post']['password'] = $pass; |
|
441 |
|
$ret['post']['gid'] = isset($d['gidnumber'][0]) ? $d['gidnumber'][0] : 0; |
|
442 |
|
$ret['post']['mail'] = $a['mail']; |
|
443 |
|
$ret['post']['server_id'] = $si['id']; |
|
444 |
|
$ret['post']['uuid'] = isset($d['entryuuid'][0]) ? $d['entryuuid'][0] : ''; |
|
445 |
|
|
|
446 |
|
$ret['ok'] = 1; |
|
447 |
|
break; |
|
448 |
|
} |
|
449 |
|
|
|
450 |
|
rg_log_exit(); |
|
451 |
|
return $ret; |
|
452 |
|
} |
|
453 |
|
|
|
454 |
|
/* |
|
455 |
|
* This is called from rg_user_login_by_user_pass. |
|
456 |
|
* It will update the ldap_cache table. |
|
457 |
|
* @post: it is the 'post' array member returned by rg_ldap_login |
|
458 |
|
*/ |
|
459 |
|
function rg_ldap_login_post($db, $uid, $post) |
|
460 |
|
{ |
|
461 |
|
rg_log_enter('ldap_login_post'); |
|
462 |
|
|
|
463 |
|
rg_log_ml('DEBUG: uid=' . $uid); |
|
464 |
|
rg_log_ml('DEBUG: post: ' . print_r($post, TRUE)); |
|
465 |
|
|
|
466 |
|
$ret = array('ok' => 0); |
|
467 |
|
while (1) { |
|
468 |
|
if ($post['uid'] != $uid) { |
|
469 |
|
rg_log('DEBUG: we need to update ldap_cache.uid'); |
|
470 |
|
$post['uid'] = $uid; |
|
471 |
|
$r = rg_ldap_sync_update_cache($db, $post); |
|
472 |
|
if ($r['ok'] != 1) { |
|
473 |
|
$ret['errmsg'] = $r['errmsg']; |
|
474 |
|
break; |
|
475 |
|
} |
|
476 |
|
} |
|
477 |
|
|
|
478 |
|
$ret['ok'] = 1; |
|
479 |
|
break; |
|
480 |
|
} |
|
481 |
|
|
|
482 |
|
rg_log_exit(); |
|
483 |
|
return $ret; |
|
484 |
|
} |
|
485 |
|
|
|
486 |
|
/* |
|
487 |
|
* High level function to list the LDAP servers |
|
488 |
|
*/ |
|
489 |
|
function rg_ldap_list_high_level($db, $rg, $paras) |
|
490 |
|
{ |
|
491 |
|
rg_prof_start('ldap_list_high_level'); |
|
492 |
|
rg_log_enter('ldap_list_high_level'); |
|
493 |
|
|
|
494 |
|
$ret = ''; |
|
495 |
|
|
|
496 |
|
$errmsg = array(); |
|
497 |
|
|
|
498 |
|
$delete = rg_var_uint('delete'); |
|
499 |
|
while ($delete == 1) { |
|
500 |
|
if (!rg_valid_referer()) { |
|
501 |
|
$errmsg[] = 'invalid referer; try again'; |
|
502 |
|
break; |
|
503 |
|
} |
|
504 |
|
|
|
505 |
|
if (!rg_token_valid($db, $rg, 'ldap_list', FALSE)) { |
|
506 |
|
$errmsg[] = 'invalid token; try again.'; |
|
507 |
|
break; |
|
508 |
|
} |
|
509 |
|
|
|
510 |
|
$list = rg_var_str('delete_list'); |
|
511 |
|
$r = rg_ldap_remove($db, $list); |
|
512 |
|
if ($r['ok'] !== 1) { |
|
513 |
|
$errmsg[] = 'cannot delete: ' . rg_ldap_error(); |
|
514 |
|
break; |
|
515 |
|
} |
|
516 |
|
|
|
517 |
|
$ret .= rg_template('admin/ldap/delete_ok.html', |
|
518 |
|
$rg, TRUE /*xss*/); |
|
519 |
|
break; |
|
520 |
|
} |
|
521 |
|
if (!empty($errmsg)) { |
|
522 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
523 |
|
$ret .= rg_template('admin/ldap/delete_err.html', |
|
524 |
|
$rg, TRUE /*xss*/); |
|
525 |
|
} |
|
526 |
|
|
|
527 |
|
$r = rg_ldap_list($db); |
|
528 |
|
if ($r['ok'] !== 1) { |
|
529 |
|
$rg['errmsg'] = rg_ldap_error(); |
|
530 |
|
$ret .= rg_template('admin/ldap/list_err.html', |
|
531 |
|
$rg, TRUE /*xss*/); |
|
532 |
|
} else { |
|
533 |
|
rg_ldap_cosmetic($db, $r['list']); |
|
534 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'ldap_list'); |
|
535 |
|
$ret .= rg_template_table('admin/ldap/list', $r['list'], $rg); |
|
536 |
|
} |
|
537 |
|
|
|
538 |
|
rg_log_exit(); |
|
539 |
|
rg_prof_end('ldap_list_high_level'); |
|
540 |
|
return $ret; |
|
541 |
|
} |
|
542 |
|
|
|
543 |
|
/* |
|
544 |
|
* High level function to add/edit a LDAP server |
|
545 |
|
*/ |
|
546 |
|
function rg_ldap_add_high_level($db, $rg, $op, $paras) |
|
547 |
|
{ |
|
548 |
|
rg_prof_start('ldap_add_high_level'); |
|
549 |
|
rg_log_enter('ldap_add_high_level op=' . $op); |
|
550 |
|
|
|
551 |
|
rg_log('DEBUG: paras:' . rg_array2string($paras)); |
|
552 |
|
|
|
553 |
|
$ret = ''; |
|
554 |
|
$errmsg = array(); |
|
555 |
|
$show_form = TRUE; |
|
556 |
|
|
|
557 |
|
$rg['ldap'] = array(); |
|
558 |
|
|
|
559 |
|
if (strcmp($op, 'add') == 0) { |
|
560 |
|
$rg['ldap']['id'] = 0; |
|
561 |
|
} else { // edit |
|
562 |
|
if (isset($paras[0])) |
|
563 |
|
$rg['ldap']['id'] = intval($paras[0]); |
|
564 |
|
else |
|
565 |
|
$rg['ldap']['id'] = 0; |
|
566 |
|
} |
|
567 |
|
|
|
568 |
|
$doit = rg_var_uint('doit'); |
|
569 |
|
while ($doit == 1) { |
|
570 |
|
if (!rg_valid_referer()) { |
|
571 |
|
$errmsg[] = 'invalid referer; try again'; |
|
572 |
|
break; |
|
573 |
|
} |
|
574 |
|
|
|
575 |
|
if (!rg_token_valid($db, $rg, 'ldap_add', FALSE)) { |
|
576 |
|
$errmsg[] = 'invalid token; try again.'; |
|
577 |
|
break; |
|
578 |
|
} |
|
579 |
|
|
|
580 |
|
$rg['ldap'] = array( |
|
581 |
|
'id' => rg_var_uint('ldap::id'), |
|
582 |
|
'name' => rg_var_str('ldap::name'), |
|
583 |
|
'plan_id' => rg_var_uint('ldap::plan_id'), |
|
584 |
|
'prio' => rg_var_uint('ldap::prio'), |
|
585 |
|
'session_time' => rg_var_uint('ldap::session_time'), |
|
586 |
|
'url' => rg_var_str('ldap::url'), |
|
587 |
|
'bind_dn' => rg_var_str('ldap::bind_dn'), |
|
588 |
|
'bind_pass' => rg_var_str('ldap::bind_pass'), |
|
589 |
|
'user_base' => rg_var_str('ldap::user_base'), |
|
590 |
|
'uid_attr' => rg_var_str('ldap::uid_attr'), |
|
591 |
|
'filter' => rg_var_str('ldap::filter'), |
|
592 |
|
'group_base' => rg_var_str('ldap::group_base'), |
|
593 |
|
'group_attr' => rg_var_str('ldap::group_attr'), |
|
594 |
|
'group_filter' => rg_var_str('ldap::group_filter'), |
|
595 |
|
'admin_group' => rg_var_str('ldap::admin_group'), |
|
596 |
|
'ca_cert' => rg_var_str('ldap::ca_cert') |
|
597 |
|
); |
|
598 |
|
|
|
599 |
|
$r = rg_ldap_add($db, $rg['login_ui']['uid'], $rg['ldap']); |
|
600 |
|
if ($r['ok'] !== 1) { |
|
601 |
|
$errmsg[] = rg_ldap_error(); |
|
602 |
|
break; |
|
603 |
|
} |
|
604 |
|
|
|
605 |
|
$ret .= rg_template('admin/ldap/edit_ok.html', |
|
606 |
|
$rg, TRUE /*xss*/); |
|
607 |
|
|
|
608 |
|
$show_form = FALSE; |
|
609 |
|
break; |
|
610 |
|
} |
|
611 |
|
|
|
612 |
|
$hints = array(); |
|
613 |
|
if ($show_form) { |
|
614 |
|
if ($doit == 0) { |
|
615 |
|
// Loading defaults values |
|
616 |
|
if (strcmp($op, 'add') == 0) { |
|
617 |
|
$rg['ldap'] = array( |
|
618 |
|
'id' => 0, |
|
619 |
|
'name' => '', |
|
620 |
|
'plan_id' => 0, |
|
621 |
|
'prio' => 0, |
|
622 |
|
'session_time' => 3600, |
|
623 |
|
'url' => '', |
|
624 |
|
'bind_dn' => '', |
|
625 |
|
'bind_pass' => '', |
|
626 |
|
'user_base' => '', |
|
627 |
|
'uid_attr' => '', |
|
628 |
|
'filter' => '', |
|
629 |
|
'group_base' => '', |
|
630 |
|
'group_attr' => '', |
|
631 |
|
'group_filter' => '', |
|
632 |
|
'admin_group' => '', |
|
633 |
|
'ca_cert' => '' |
|
634 |
|
); |
|
635 |
|
} else { // edit |
|
636 |
|
$_id = $rg['ldap']['id']; |
|
637 |
|
$r = rg_ldap_list($db); |
|
638 |
|
if ($r['ok'] != 1) { |
|
639 |
|
$errmsg[] = 'cannot load info; try again later'; |
|
640 |
|
} else if (!isset($r['list'][$_id])) { |
|
641 |
|
$errmsg[] = 'invalid id'; |
|
642 |
|
} else { |
|
643 |
|
$rg['ldap'] = $r['list'][$_id]; |
|
644 |
|
} |
|
645 |
|
} |
|
646 |
|
} |
|
647 |
|
|
|
648 |
|
$rg['HTML:select_plan'] = rg_plan_select($db, 'ldap::plan-id', |
|
649 |
|
$rg['ldap']['plan_id']); |
|
650 |
|
|
|
651 |
|
$hints[]['HTML:hint'] = rg_template( |
|
652 |
|
'admin/ldap/hints.html', $rg, TRUE /*xss*/); |
|
653 |
|
|
|
654 |
|
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
655 |
|
$rg['rg_form_token'] = rg_token_get($db, $rg, 'ldap_add'); |
|
656 |
|
$ret .= rg_template('admin/ldap/add_edit.html', |
|
657 |
|
$rg, TRUE /*xss*/); |
|
658 |
|
} else { |
|
659 |
|
$hints[]['HTML:hint'] = rg_template( |
|
660 |
|
'admin/ldap/hints.html', $rg, TRUE /*xss*/); |
|
661 |
|
} |
|
662 |
|
|
|
663 |
|
$ret .= rg_template_table('hints/list', $hints, $rg); |
|
664 |
|
|
|
665 |
|
rg_log_exit(); |
|
666 |
|
rg_prof_end('ldap_add_high_level'); |
|
667 |
|
return $ret; |
|
668 |
|
} |
|
669 |
|
|
|
670 |
|
/* |
|
671 |
|
* Main HL function for LDAP |
|
672 |
|
* (Admin -> LDAP) |
|
673 |
|
*/ |
|
674 |
|
function rg_ldap_high_level($db, &$rg, $paras) |
|
675 |
|
{ |
|
676 |
|
rg_prof_start('ldap_high_level'); |
|
677 |
|
rg_log_enter('ldap_high_level'); |
|
678 |
|
|
|
679 |
|
$ret = ''; |
|
680 |
|
while (1) { |
|
681 |
|
$op = empty($paras) ? 'list' : array_shift($paras); |
|
682 |
|
$rg['menu']['ldap'][$op] = 1; |
|
683 |
|
|
|
684 |
|
$rg['HTML:menu_level2'] = |
|
685 |
|
rg_template('admin/ldap/menu.html', $rg, TRUE /*xss*/); |
|
686 |
|
|
|
687 |
|
switch ($op) { |
|
688 |
|
case 'add': |
|
689 |
|
case 'edit': |
|
690 |
|
$ret .= rg_ldap_add_high_level($db, $rg, $op, $paras); |
|
691 |
|
break; |
|
692 |
|
|
|
693 |
|
default: |
|
694 |
|
$ret .= rg_ldap_list_high_level($db, $rg, $paras); |
|
695 |
|
break; |
|
696 |
|
} |
|
697 |
|
|
|
698 |
|
break; |
|
699 |
|
} |
|
700 |
|
|
|
701 |
|
rg_log_exit(); |
|
702 |
|
rg_prof_end('ldap_high_level'); |
|
703 |
|
return $ret; |
|
704 |
|
} |
|
705 |
|
|
|
706 |
|
?> |
File inc/ldap_sync.inc.php added (mode: 100644) (index 0000000..c3b86e4) |
|
1 |
|
<?php |
|
2 |
|
require_once($INC . "/sql.inc.php"); |
|
3 |
|
require_once($INC . "/state.inc.php"); |
|
4 |
|
require_once($INC . "/prof.inc.php"); |
|
5 |
|
require_once($INC . "/ldap_core.inc.php"); |
|
6 |
|
|
|
7 |
|
/* |
|
8 |
|
* Get data from cache |
|
9 |
|
*/ |
|
10 |
|
function rg_ldap_sync_get_cache($db, $v) |
|
11 |
|
{ |
|
12 |
|
rg_log_enter('ldap_sync_get_cache'); |
|
13 |
|
|
|
14 |
|
$ret = array('ok' => 0); |
|
15 |
|
while (1) { |
|
16 |
|
$params = array('v' => $v); |
|
17 |
|
$sql = 'SELECT * FROM ldap_cache' |
|
18 |
|
. ' WHERE mail = @@v@@' |
|
19 |
|
. ' OR ldap_uid = @@v@@' |
|
20 |
|
. ' OR cn = @@v@@' |
|
21 |
|
. ' ORDER BY prio'; |
|
22 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
23 |
|
if ($res === FALSE) { |
|
24 |
|
$ret['errmsg'] = 'cannot select from cache'; |
|
25 |
|
break; |
|
26 |
|
} |
|
27 |
|
|
|
28 |
|
$ret['list'] = array(); |
|
29 |
|
while (($row = rg_sql_fetch_array($res))) |
|
30 |
|
$ret['list'][] = $row; |
|
31 |
|
|
|
32 |
|
rg_sql_free_result($res); |
|
33 |
|
|
|
34 |
|
$ret['ok'] = 1; |
|
35 |
|
break; |
|
36 |
|
} |
|
37 |
|
|
|
38 |
|
rg_log_exit(); |
|
39 |
|
return $ret; |
|
40 |
|
} |
|
41 |
|
|
|
42 |
|
/* |
|
43 |
|
* Updates ldap_cache table |
|
44 |
|
* TODO: should be moved to ldap.inc.php because is called from there? |
|
45 |
|
* And get rid of "_sync_" in name. |
|
46 |
|
*/ |
|
47 |
|
function rg_ldap_sync_update_cache($db, $l) |
|
48 |
|
{ |
|
49 |
|
rg_log_enter('ldap_sync_update_cache'); |
|
50 |
|
|
|
51 |
|
rg_log_ml('DEBUG: l: ' . print_r($l, TRUE)); |
|
52 |
|
|
|
53 |
|
$ret = array('ok' => 0); |
|
54 |
|
while (1) { |
|
55 |
|
// We update uid only if != 0 |
|
56 |
|
$add = ''; |
|
57 |
|
if ($l['uid'] > 0) |
|
58 |
|
$add .= ', uid = @@uid@@'; |
|
59 |
|
|
|
60 |
|
$sql = 'UPDATE ldap_cache SET' |
|
61 |
|
. ' ldap_uid = @@ldap_uid@@' |
|
62 |
|
. $add |
|
63 |
|
. ', password = @@password@@' |
|
64 |
|
. ', sn = @@sn@@' |
|
65 |
|
. ', gn = @@gn@@' |
|
66 |
|
. ', gid = @@gid@@' |
|
67 |
|
. ', mail = @@mail@@' |
|
68 |
|
. ', cn = @@cn@@' |
|
69 |
|
. ', shadow_expire = @@shadow_expire@@' |
|
70 |
|
. ' WHERE server_id = @@server_id@@' |
|
71 |
|
. ' AND uuid = @@uuid@@'; |
|
72 |
|
$res = rg_sql_query_params($db, $sql, $l); |
|
73 |
|
if ($res === FALSE) { |
|
74 |
|
$ret['errmsg'] = 'error in update'; |
|
75 |
|
break; |
|
76 |
|
} |
|
77 |
|
$arows = rg_sql_affected_rows($res); |
|
78 |
|
rg_sql_free_result($res); |
|
79 |
|
|
|
80 |
|
if ($arows > 0) { |
|
81 |
|
$ret['ok'] = 1; |
|
82 |
|
break; |
|
83 |
|
} |
|
84 |
|
|
|
85 |
|
$sql = 'INSERT INTO ldap_cache (uid, ldap_uid, password' |
|
86 |
|
. ', sn, gn, gid, mail, cn, shadow_expire' |
|
87 |
|
. ', server_id, uuid)' |
|
88 |
|
. ' VALUES (@@uid@@, @@ldap_uid@@, @@password@@' |
|
89 |
|
. ', @@sn@@, @@gn@@, @@gid@@, @@mail@@' |
|
90 |
|
. ', @@cn@@, @@shadow_expire@@, @@server_id@@' |
|
91 |
|
. ', @@uuid@@)'; |
|
92 |
|
$ignore = array(RG_SQL_UNIQUE_VIOLATION); |
|
93 |
|
$res = rg_sql_query_params_ignore($db, $sql, $l, |
|
94 |
|
$ignore, $ignore_kicked); |
|
95 |
|
if ($res === FALSE) { |
|
96 |
|
if (!$ignore_kicked) { |
|
97 |
|
$ret['errmsg'] = 'error in update'; |
|
98 |
|
break; |
|
99 |
|
} |
|
100 |
|
rg_log('Entry already in cache.'); |
|
101 |
|
} else { |
|
102 |
|
rg_sql_free_result($res); |
|
103 |
|
} |
|
104 |
|
|
|
105 |
|
$ret['ok'] = 1; |
|
106 |
|
break; |
|
107 |
|
} |
|
108 |
|
|
|
109 |
|
rg_log_exit(); |
|
110 |
|
return $ret; |
|
111 |
|
} |
|
112 |
|
|
|
113 |
|
/* |
|
114 |
|
* Updates ldap_servers table - for now, CSNs |
|
115 |
|
* TODO: It should be used to set also the last error message? |
|
116 |
|
* Maybe we should have a different log for this kind of problems, |
|
117 |
|
* and send it to the admin. |
|
118 |
|
*/ |
|
119 |
|
function rg_ldap_sync_update_server($db, $server_id, $csn) |
|
120 |
|
{ |
|
121 |
|
rg_log_enter('ldap_sync_update_server'); |
|
122 |
|
|
|
123 |
|
$ret = array('ok' => 0); |
|
124 |
|
while (1) { |
|
125 |
|
if (empty($csn)) { |
|
126 |
|
$ret['ok'] = 1; |
|
127 |
|
break; |
|
128 |
|
} |
|
129 |
|
|
|
130 |
|
$params = array( |
|
131 |
|
'server_id' => $server_id, |
|
132 |
|
'csn' => $csn |
|
133 |
|
); |
|
134 |
|
$sql = 'UPDATE ldap_servers SET' |
|
135 |
|
. ' csn = @@csn@@' |
|
136 |
|
. ' WHERE id = @@server_id@@'; |
|
137 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
138 |
|
if ($res === FALSE) { |
|
139 |
|
$ret['errmsg'] = 'error in update'; |
|
140 |
|
break; |
|
141 |
|
} |
|
142 |
|
rg_sql_free_result($res); |
|
143 |
|
|
|
144 |
|
$ret['ok'] = 1; |
|
145 |
|
break; |
|
146 |
|
} |
|
147 |
|
|
|
148 |
|
rg_log_exit(); |
|
149 |
|
return $ret; |
|
150 |
|
} |
|
151 |
|
|
|
152 |
|
/* |
|
153 |
|
* It applies the updates to the database. |
|
154 |
|
* Input is a ldif parsed as an array (from rg_ldap_core_ldif2array) |
|
155 |
|
*/ |
|
156 |
|
function rg_ldap_sync_apply($db, $server_id, $data) |
|
157 |
|
{ |
|
158 |
|
rg_log_enter('ldap_sync_apply'); |
|
159 |
|
|
|
160 |
|
$ret = array(); |
|
161 |
|
$ret['ok'] = 0; |
|
162 |
|
while (1) { |
|
163 |
|
rg_log_ml('data: ' . print_r($data, TRUE)); |
|
164 |
|
|
|
165 |
|
if (rg_sql_begin($db) !== TRUE) { |
|
166 |
|
$ret['errmsg'] = 'cannot start transaction'; |
|
167 |
|
break; |
|
168 |
|
} |
|
169 |
|
$rollback = TRUE; |
|
170 |
|
|
|
171 |
|
$csn = array(); |
|
172 |
|
foreach ($data as $block_id => $block) { |
|
173 |
|
if (isset($block['entryCSN'][0])) { |
|
174 |
|
rg_log('DEBUG: entryCSN is present!'); |
|
175 |
|
$c = $block['entryCSN'][0]; |
|
176 |
|
// Example: 20171001075924.155248Z#000000#001#000000 |
|
177 |
|
$_t = explode('#', $c); |
|
178 |
|
$_s = isset($_t[2]) ? $_t[2] : ''; |
|
179 |
|
if (!isset($csn[$_s]) || ($c > $csn[$_s])) |
|
180 |
|
$csn[$_s] = $c; |
|
181 |
|
} else { |
|
182 |
|
rg_log('DEBUG: entryCSN is NOT present!'); |
|
183 |
|
} |
|
184 |
|
|
|
185 |
|
if (!isset($block['objectClass'])) { |
|
186 |
|
$ret['errmsg'] = 'missing objectClass'; |
|
187 |
|
break; |
|
188 |
|
} |
|
189 |
|
|
|
190 |
|
// Try to detect if is a user entry |
|
191 |
|
$is_user = FALSE; |
|
192 |
|
foreach ($block['objectClass'] as $oc) { |
|
193 |
|
if (strcasecmp($oc, 'inetOrgPerson') == 0) { |
|
194 |
|
$is_user = TRUE; |
|
195 |
|
break; |
|
196 |
|
} |
|
197 |
|
} |
|
198 |
|
|
|
199 |
|
if (!$is_user) |
|
200 |
|
continue; |
|
201 |
|
|
|
202 |
|
$l = array(); |
|
203 |
|
$l['uid'] = 0; |
|
204 |
|
$l['ldap_uid'] = isset($block['uid'][0]) ? $block['uid'][0] : ''; |
|
205 |
|
$l['password'] = isset($block['userPassword'][0]) ? $block['userPassword'][0] : ''; |
|
206 |
|
$l['sn'] = isset($block['sn'][0]) ? $block['sn'][0] : ''; |
|
207 |
|
$l['gn'] = isset($block['givenName'][0]) ? $block['givenName'][0] : ''; |
|
208 |
|
$l['gid'] = isset($block['gidNumber'][0]) ? $block['gidNumber'][0] : 0; |
|
209 |
|
$l['mail'] = isset($block['mail'][0]) ? $block['mail'][0] : ''; |
|
210 |
|
$l['cn'] = isset($block['cn'][0]) ? $block['cn'][0] : ''; |
|
211 |
|
$l['shadow_expire'] = isset($block['shadowExpire'][0]) ? $block['shadowExpire'][0] : '99999'; |
|
212 |
|
$l['server_id'] = $server_id; |
|
213 |
|
$l['uuid'] = isset($block['entryUUID'][0]) ? $block['entryUUID'][0] : ''; |
|
214 |
|
// Verifications |
|
215 |
|
if (empty($l['ldap_uid'])) { |
|
216 |
|
rg_log('DEBUG: ldap_uid is not present!'); |
|
217 |
|
continue; |
|
218 |
|
} |
|
219 |
|
if (empty($l['uuid'])) { |
|
220 |
|
rg_log('DEBUG: entryUUID is not present!'); |
|
221 |
|
continue; |
|
222 |
|
} |
|
223 |
|
|
|
224 |
|
rg_log_ml('DEBUG: l:' . print_r($l, TRUE)); |
|
225 |
|
|
|
226 |
|
$r = rg_ldap_sync_update_cache($db, $l); |
|
227 |
|
if ($r['ok'] !== 1) { |
|
228 |
|
$r['errmsg'] = $r['errmsg']; |
|
229 |
|
break; |
|
230 |
|
} |
|
231 |
|
|
|
232 |
|
/* |
|
233 |
|
TODO foreach ($block['memberOf'] as $m) |
|
234 |
|
$pairs_groups[] = array($uuid, $m); |
|
235 |
|
*/ |
|
236 |
|
} |
|
237 |
|
if (isset($ret['errmsg'])) |
|
238 |
|
break; |
|
239 |
|
|
|
240 |
|
rg_log_ml('DEBUG: csn: ' . print_r($csn, TRUE)); |
|
241 |
|
$r = rg_ldap_sync_update_server($db, $server_id, |
|
242 |
|
implode(';', $csn)); |
|
243 |
|
if ($r['ok'] !== 1) { |
|
244 |
|
$ret['errmsg'] = $r['errmsg']; |
|
245 |
|
break; |
|
246 |
|
} |
|
247 |
|
|
|
248 |
|
if (rg_sql_commit($db) !== TRUE) { |
|
249 |
|
$ret['errmsg'] = 'cannot commit'; |
|
250 |
|
break; |
|
251 |
|
} |
|
252 |
|
|
|
253 |
|
$ret['ok'] = 1; |
|
254 |
|
$rollback = FALSE; |
|
255 |
|
break; |
|
256 |
|
} |
|
257 |
|
|
|
258 |
|
if ($rollback) |
|
259 |
|
rg_sql_rollback($db); |
|
260 |
|
|
|
261 |
|
rg_log_exit(); |
|
262 |
|
return $ret; |
|
263 |
|
} |
|
264 |
|
|
|
265 |
|
/* |
|
266 |
|
* Function called to process raw ldif blocks -> database |
|
267 |
|
*/ |
|
268 |
|
function rg_ldap_sync_data($db, $server_id, $s) |
|
269 |
|
{ |
|
270 |
|
rg_log_enter('ldap_sync_data'); |
|
271 |
|
rg_log('DEBUG: s=' . $s); |
|
272 |
|
|
|
273 |
|
$ret = array(); |
|
274 |
|
$ret['ok'] = 0; |
|
275 |
|
while (1) { |
|
276 |
|
$a = rg_ldap_core_ldif2array($s); |
|
277 |
|
if ($a['ok'] != 1) { |
|
278 |
|
$ret['errmsg'] = $a['errmsg']; |
|
279 |
|
break; |
|
280 |
|
} |
|
281 |
|
|
|
282 |
|
// Update database |
|
283 |
|
if (!empty($a['data'])) { |
|
284 |
|
$r = rg_ldap_sync_apply($db, $server_id, $a['data']); |
|
285 |
|
if ($r['ok'] != 1) { |
|
286 |
|
$ret['errmsg'] = $r['errmsg']; |
|
287 |
|
break; |
|
288 |
|
} |
|
289 |
|
} |
|
290 |
|
|
|
291 |
|
$ret['ok'] = 1; |
|
292 |
|
$ret['used'] = $a['used']; |
|
293 |
|
break; |
|
294 |
|
} |
|
295 |
|
|
|
296 |
|
rg_log_exit(); |
|
297 |
|
return $ret; |
|
298 |
|
} |
|
299 |
|
|
|
300 |
|
/* |
|
301 |
|
* 'input' callback for rg_ldap_sync_* functions |
|
302 |
|
*/ |
|
303 |
|
function rg_ldap_sync_cb_input($index, &$info, $stream) |
|
304 |
|
{ |
|
305 |
|
rg_log_enter('ldap_sync_cb_input: index=' . $index |
|
306 |
|
. ' stream=' . $stream); |
|
307 |
|
|
|
308 |
|
while (1) { |
|
309 |
|
//rg_log_ml('info: ' . print_r($info, TRUE)); |
|
310 |
|
|
|
311 |
|
$c = &$info['custom']; |
|
312 |
|
|
|
313 |
|
switch ($stream) { |
|
314 |
|
case 1: |
|
315 |
|
//rg_log('Got data: ' . $info['in_buf']); |
|
316 |
|
$r = rg_ldap_sync_data($c['db'], $c['server_id'], |
|
317 |
|
$info['in_buf']); |
|
318 |
|
if ($r['ok'] != 1) { |
|
319 |
|
rg_log('Error: ' . $r['errmsg']); |
|
320 |
|
$info['done'] = TRUE; |
|
321 |
|
break; |
|
322 |
|
} |
|
323 |
|
|
|
324 |
|
$info['in_buf'] = substr($info['in_buf'], $r['used']); |
|
325 |
|
break; |
|
326 |
|
|
|
327 |
|
case 2: |
|
328 |
|
// TODO: should we do something with this? |
|
329 |
|
// Maybe store it in the synchronization log? |
|
330 |
|
// Send it do admin? |
|
331 |
|
rg_log_ml('error received: ' . $info['err_buf']); |
|
332 |
|
$info['err_buf'] = ''; |
|
333 |
|
break; |
|
334 |
|
} |
|
335 |
|
|
|
336 |
|
break; |
|
337 |
|
} |
|
338 |
|
|
|
339 |
|
rg_log_exit(); |
|
340 |
|
} |
|
341 |
|
|
|
342 |
|
/* |
|
343 |
|
* 'error' calback for rg_ldap_sync_* functions |
|
344 |
|
*/ |
|
345 |
|
function rg_ldap_sync_cb_error($index, &$info, $msg) |
|
346 |
|
{ |
|
347 |
|
rg_log('ldap_sync_cb_error: ' . $msg); |
|
348 |
|
$info['done'] = TRUE; |
|
349 |
|
} |
|
350 |
|
|
|
351 |
|
/* |
|
352 |
|
* Sync function using SyncRepl protocol (ro way) |
|
353 |
|
*/ |
|
354 |
|
function rg_ldap_sync_ro($db, $data) |
|
355 |
|
{ |
|
356 |
|
// TODO: move this in the higher level part |
|
357 |
|
// Load the list of servers in decreasing priority order |
|
358 |
|
// because we want the best one to overwrite the lower priority ones. |
|
359 |
|
|
|
360 |
|
// Hm! Have a problem: sync_rp with multiple servers! |
|
361 |
|
|
|
362 |
|
$ret = array(); |
|
363 |
|
$ret['ok'] = 0; |
|
364 |
|
while (1) { |
|
365 |
|
// Store password |
|
366 |
|
$r = rg_id(16); |
|
367 |
|
// TODO: choose a better name; choose a better dir |
|
368 |
|
$pass_file = '/tmp/' . $r; |
|
369 |
|
$f = @fopen($pass_file, 'w'); |
|
370 |
|
if ($f === FALSE) { |
|
371 |
|
$ret['errmsg'] = 'cannot create pass file'; |
|
372 |
|
break; |
|
373 |
|
} |
|
374 |
|
if (@chmod($pass_file, 0600) !== TRUE) { |
|
375 |
|
fclose($f); |
|
376 |
|
$ret['errmsg'] = 'cannot chmod pass'; |
|
377 |
|
break; |
|
378 |
|
} |
|
379 |
|
|
|
380 |
|
$r = @fwrite($f, $data['bind_pass']); |
|
381 |
|
if ($r === FALSE) { |
|
382 |
|
fclose($f); |
|
383 |
|
$ret['errmsg'] = 'cannot write pass'; |
|
384 |
|
break; |
|
385 |
|
} |
|
386 |
|
|
|
387 |
|
fclose($f); |
|
388 |
|
|
|
389 |
|
$cmd = 'ldapsearch -d-1 -LLL -v -b ' . escapeshellarg($data['base']) |
|
390 |
|
. ' -x -H ldap://' . escapeshellarg($data['addr']) |
|
391 |
|
. ':' . escapeshellarg($data['port']) |
|
392 |
|
. ' -D ' . escapeshellarg($data['bind_user']) |
|
393 |
|
. ' -y ' . escapeshellarg($pass_file) |
|
394 |
|
. ' -s sub -P 3'; |
|
395 |
|
if (isset($data['rid']) && isset($data['csn'])) { |
|
396 |
|
$cmd .= ' -E ' . escapeshellarg('sync=ro/' |
|
397 |
|
. 'rid=' . $data['rid'] |
|
398 |
|
. ',sid=001' |
|
399 |
|
. ',csn=' . $data['csn']); |
|
400 |
|
} else { |
|
401 |
|
$cmd .= ' -E sync=ro/rid=001,sid=001,csn=aaa'; |
|
402 |
|
} |
|
403 |
|
|
|
404 |
|
if (isset($data['fields'])) { |
|
405 |
|
$fields = ''; |
|
406 |
|
$add = ''; |
|
407 |
|
foreach($data['fields'] as $f) { |
|
408 |
|
$fields .= $add . $f; |
|
409 |
|
$add = ','; |
|
410 |
|
} |
|
411 |
|
} else { |
|
412 |
|
$fields = '*'; |
|
413 |
|
} |
|
414 |
|
|
|
415 |
|
$cmd .= ' "(|' |
|
416 |
|
. '(objectClass=groupOfNames)' |
|
417 |
|
. '(objectClass=groupOfUniqueNames)' |
|
418 |
|
. '(structuralObjectClass=inetOrgPerson)' |
|
419 |
|
. ')"'; |
|
420 |
|
$cmd .= ' ' . escapeshellarg($fields) . ' +'; |
|
421 |
|
$a = array( |
|
422 |
|
'cmds' => array( |
|
423 |
|
'cmd1' => array( |
|
424 |
|
'cmd' => $cmd, |
|
425 |
|
'cb_input' => 'rg_ldap_sync_cb_input', |
|
426 |
|
'cb_error' => 'rg_ldap_sync_cb_error', |
|
427 |
|
'custom' => array( |
|
428 |
|
'db' => $db, |
|
429 |
|
'server_id' => $data['server_id'] |
|
430 |
|
) |
|
431 |
|
) |
|
432 |
|
) |
|
433 |
|
); |
|
434 |
|
$r = rg_exec2($a); |
|
435 |
|
@unlink($pass_file); |
|
436 |
|
if ($r['ok'] != 1) { |
|
437 |
|
$ret['errmsg'] = $r['errmsg']; |
|
438 |
|
break; |
|
439 |
|
} |
|
440 |
|
|
|
441 |
|
$ret['ok'] = 1; |
|
442 |
|
break; |
|
443 |
|
} |
|
444 |
|
|
|
445 |
|
return $ret; |
|
446 |
|
} |
|
447 |
|
|
|
448 |
|
?> |
File inc/sql.inc.php changed (mode: 100644) (index 10abc86..2b95172) |
2 |
2 |
require_once($INC . "/log.inc.php"); |
require_once($INC . "/log.inc.php"); |
3 |
3 |
require_once($INC . "/prof.inc.php"); |
require_once($INC . "/prof.inc.php"); |
4 |
4 |
|
|
|
5 |
|
// Some constants for sql error codes |
|
6 |
|
define('RG_SQL_UNIQUE_VIOLATION', '23505'); |
|
7 |
|
|
5 |
8 |
if (!function_exists("pg_connect")) |
if (!function_exists("pg_connect")) |
6 |
9 |
die("FATAL: php PostgreSQL is not installed!"); |
die("FATAL: php PostgreSQL is not installed!"); |
7 |
10 |
|
|
|
11 |
|
if (!isset($rg_sql_debug)) |
|
12 |
|
$rg_sql_debug = 0; |
|
13 |
|
|
8 |
14 |
$rg_sql_conn = array(); |
$rg_sql_conn = array(); |
9 |
15 |
|
|
10 |
16 |
$rg_sql_error = ""; |
$rg_sql_error = ""; |
|
... |
... |
function rg_sql_set_error($str) |
17 |
23 |
{ |
{ |
18 |
24 |
global $rg_sql_error; |
global $rg_sql_error; |
19 |
25 |
$rg_sql_error = $str; |
$rg_sql_error = $str; |
20 |
|
rg_log($str); |
|
|
26 |
|
rg_log('sql_set_error: ' . $str); |
21 |
27 |
} |
} |
22 |
28 |
|
|
23 |
29 |
function rg_sql_error() |
function rg_sql_error() |
|
... |
... |
function rg_sql_app($name) |
42 |
48 |
*/ |
*/ |
43 |
49 |
function rg_sql_open_nodelay($h) |
function rg_sql_open_nodelay($h) |
44 |
50 |
{ |
{ |
45 |
|
global $php_errormsg; |
|
46 |
51 |
global $rg_sql_debug; |
global $rg_sql_debug; |
47 |
52 |
global $rg_sql_conn; |
global $rg_sql_conn; |
48 |
53 |
|
|
49 |
|
rg_prof_start("sql_open_nodelay"); |
|
|
54 |
|
if ($rg_sql_debug > 20) |
|
55 |
|
rg_log_enter('sql_open_nodelay'); |
50 |
56 |
|
|
51 |
57 |
$ret = FALSE; |
$ret = FALSE; |
52 |
58 |
while (1) { |
while (1) { |
|
... |
... |
function rg_sql_open_nodelay($h) |
55 |
61 |
break; |
break; |
56 |
62 |
} |
} |
57 |
63 |
|
|
|
64 |
|
if ($rg_sql_debug > 40) { |
|
65 |
|
rg_log('My pid: ' . getmypid()); |
|
66 |
|
rg_log_ml('DEBUG: rg_sql_conn: ' . print_r($rg_sql_conn, TRUE)); |
|
67 |
|
} |
|
68 |
|
|
58 |
69 |
if (isset($rg_sql_conn[$h]['db'])) { |
if (isset($rg_sql_conn[$h]['db'])) { |
59 |
|
$ret = $rg_sql_conn[$h]['db']; |
|
60 |
|
break; |
|
|
70 |
|
if (getmypid() == $rg_sql_conn[$h]['pid']) { |
|
71 |
|
if ($rg_sql_debug > 30) |
|
72 |
|
rg_log('DB: Same pid, reuse connection'); |
|
73 |
|
$ret = $rg_sql_conn[$h]['db']; |
|
74 |
|
break; |
|
75 |
|
} |
|
76 |
|
|
|
77 |
|
if ($rg_sql_debug > 25) |
|
78 |
|
rg_log('DB: pid is different, reconnecting...'); |
|
79 |
|
unset($rg_sql_conn[$h]['db']); |
61 |
80 |
} |
} |
62 |
81 |
|
|
63 |
82 |
putenv('PGAPPNAME=' . $rg_sql_conn[$h]['app']); |
putenv('PGAPPNAME=' . $rg_sql_conn[$h]['app']); |
|
... |
... |
function rg_sql_open_nodelay($h) |
66 |
85 |
if ($rg_sql_debug > 0) |
if ($rg_sql_debug > 0) |
67 |
86 |
rg_log("DB: opening [$str]..."); |
rg_log("DB: opening [$str]..."); |
68 |
87 |
|
|
69 |
|
rg_prof_set(array("db_conn" => 1)); |
|
|
88 |
|
rg_prof_set(array('db_conn' => 1)); |
|
89 |
|
|
|
90 |
|
// This is used to test if we forked |
|
91 |
|
$rg_sql_conn[$h]['pid'] = getmypid(); |
70 |
92 |
|
|
71 |
93 |
$_s = microtime(TRUE); |
$_s = microtime(TRUE); |
72 |
94 |
|
|
|
... |
... |
function rg_sql_open_nodelay($h) |
88 |
110 |
$db = FALSE; |
$db = FALSE; |
89 |
111 |
break; |
break; |
90 |
112 |
} |
} |
|
113 |
|
sleep(1); |
91 |
114 |
} |
} |
92 |
115 |
$diff = intval((microtime(TRUE) - $_s) * 1000); |
$diff = intval((microtime(TRUE) - $_s) * 1000); |
93 |
|
rg_prof_set(array("db_c_ms" => $diff)); |
|
|
116 |
|
rg_prof_set(array('db_c_ms' => $diff)); |
94 |
117 |
if ($db === FALSE) { |
if ($db === FALSE) { |
95 |
118 |
$err = 'cannot connect to database'; |
$err = 'cannot connect to database'; |
96 |
119 |
rg_sql_set_error($err); |
rg_sql_set_error($err); |
|
... |
... |
function rg_sql_open_nodelay($h) |
104 |
127 |
break; |
break; |
105 |
128 |
} |
} |
106 |
129 |
|
|
107 |
|
rg_prof_end("sql_open_nodelay"); |
|
|
130 |
|
if ($rg_sql_debug > 20) |
|
131 |
|
rg_log_exit(); |
108 |
132 |
return $ret; |
return $ret; |
109 |
133 |
} |
} |
110 |
134 |
|
|
|
... |
... |
function rg_sql_open($str) |
118 |
142 |
global $rg_sql_app; |
global $rg_sql_app; |
119 |
143 |
|
|
120 |
144 |
$free_index = count($rg_sql_conn); |
$free_index = count($rg_sql_conn); |
121 |
|
$rg_sql_conn[$free_index] = array(); |
|
122 |
|
$rg_sql_conn[$free_index]['str'] = $str; |
|
123 |
|
$rg_sql_conn[$free_index]['app'] = $rg_sql_app; |
|
|
145 |
|
$rg_sql_conn[$free_index] = array( |
|
146 |
|
'str' => $str, |
|
147 |
|
'app' => $rg_sql_app |
|
148 |
|
); |
124 |
149 |
|
|
125 |
150 |
//rg_log("Delay connection to [$str], index $free_index."); |
//rg_log("Delay connection to [$str], index $free_index."); |
126 |
151 |
return $free_index; |
return $free_index; |
|
... |
... |
function rg_sql_escape($h, $str) |
141 |
166 |
/* |
/* |
142 |
167 |
* Helper for sql_query and sql_query_params |
* Helper for sql_query and sql_query_params |
143 |
168 |
*/ |
*/ |
144 |
|
function rg_sql_query0($db, $sql, $res, $_s) |
|
|
169 |
|
function rg_sql_query0($db, $sql, $r, $start_ts, $ignore, &$ignore_kicked) |
145 |
170 |
{ |
{ |
146 |
171 |
global $rg_sql_debug; |
global $rg_sql_debug; |
147 |
172 |
|
|
|
173 |
|
$ignore_kicked = FALSE; |
148 |
174 |
while (1) { |
while (1) { |
|
175 |
|
if ($r !== TRUE) { |
|
176 |
|
$err = "$sql: send: " . @pg_last_error($db); |
|
177 |
|
$res = FALSE; |
|
178 |
|
break; |
|
179 |
|
} |
|
180 |
|
|
|
181 |
|
$res = @pg_get_result($db); |
149 |
182 |
if ($res === FALSE) { |
if ($res === FALSE) { |
150 |
|
$err = "$sql: " . @pg_last_error($db); |
|
151 |
|
rg_sql_set_error($err); |
|
152 |
|
rg_internal_error($err); |
|
153 |
|
rg_prof_set(array('qerrors' => 1)); |
|
154 |
|
// reconnect if needed |
|
155 |
|
@pg_ping($db); |
|
|
183 |
|
$err = $sql . ': get: no pending query'; |
156 |
184 |
break; |
break; |
157 |
185 |
} |
} |
158 |
186 |
|
|
159 |
|
$diff = sprintf("%u", (microtime(TRUE) - $_s) * 1000); |
|
|
187 |
|
$state = rg_sql_last_error_code($res); |
|
188 |
|
if ($state === FALSE) { |
|
189 |
|
$err = $sql . ': get: pg_result_error_field error'; |
|
190 |
|
break; |
|
191 |
|
} |
|
192 |
|
if (($state !== NULL) && (strcmp($state, '00000') !== 0)) { |
|
193 |
|
foreach ($ignore as $code) { |
|
194 |
|
if (strcmp($code, $state) == 0) { |
|
195 |
|
$ignore_kicked = TRUE; |
|
196 |
|
break; |
|
197 |
|
} |
|
198 |
|
} |
|
199 |
|
|
|
200 |
|
if ($ignore_kicked) |
|
201 |
|
if ($rg_sql_debug > 50) |
|
202 |
|
rg_log('DB: We should ignore the error!'); |
|
203 |
|
|
|
204 |
|
$err = $sql . ': ' . @pg_last_error($db) . ' (' . $state . ')'; |
|
205 |
|
@pg_free_result($res); |
|
206 |
|
$res = FALSE; |
|
207 |
|
break; |
|
208 |
|
} |
|
209 |
|
|
|
210 |
|
$diff = sprintf("%u", (microtime(TRUE) - $start_ts) * 1000); |
160 |
211 |
$rows = rg_sql_num_rows($res); |
$rows = rg_sql_num_rows($res); |
161 |
212 |
if ($rows == 0) |
if ($rows == 0) |
162 |
213 |
$arows = rg_sql_affected_rows($res); |
$arows = rg_sql_affected_rows($res); |
|
... |
... |
function rg_sql_query0($db, $sql, $res, $_s) |
173 |
224 |
break; |
break; |
174 |
225 |
} |
} |
175 |
226 |
|
|
|
227 |
|
if ($res === FALSE) { |
|
228 |
|
rg_sql_set_error($err); |
|
229 |
|
if (!$ignore_kicked) { |
|
230 |
|
rg_internal_error($err); |
|
231 |
|
rg_prof_set(array('qerrors' => 1)); |
|
232 |
|
} |
|
233 |
|
// reconnect if needed |
|
234 |
|
@pg_ping($db); |
|
235 |
|
} |
|
236 |
|
|
176 |
237 |
return $res; |
return $res; |
177 |
238 |
|
|
178 |
239 |
} |
} |
|
... |
... |
function rg_sql_query($h, $sql) |
193 |
254 |
if ($db === FALSE) |
if ($db === FALSE) |
194 |
255 |
break; |
break; |
195 |
256 |
|
|
196 |
|
$_s = microtime(TRUE); |
|
197 |
|
$res = @pg_query($db, $sql); |
|
198 |
|
$ret = rg_sql_query0($db, $sql, $res, $_s); |
|
|
257 |
|
$ignore = array(); |
|
258 |
|
$start_ts = microtime(TRUE); |
|
259 |
|
$r = @pg_send_query($db, $sql); |
|
260 |
|
$ret = rg_sql_query0($db, $sql, $r, $start_ts, |
|
261 |
|
$ignore, $ignore_kicked); |
199 |
262 |
break; |
break; |
200 |
263 |
} |
} |
201 |
264 |
|
|
|
... |
... |
function rg_sql_query($h, $sql) |
207 |
270 |
/* |
/* |
208 |
271 |
* Queries using params |
* Queries using params |
209 |
272 |
* @params - array of fields -> values |
* @params - array of fields -> values |
|
273 |
|
* @ignore - array of strings with errors we should not log as internal errors |
|
274 |
|
* See https://www.postgresql.org/docs/current/static/errcodes-appendix.html |
|
275 |
|
* @ignore_kicked will be set to true if the error is in @ignore array |
210 |
276 |
* Examples: $params = array("id" => "1", "name" = "bau") |
* Examples: $params = array("id" => "1", "name" = "bau") |
211 |
277 |
* $sql = "UPDATE x SET name = @@name@@ WHERE id = @@id@@ AND @@name@@ = @@name@@" |
* $sql = "UPDATE x SET name = @@name@@ WHERE id = @@id@@ AND @@name@@ = @@name@@" |
212 |
|
* $sql2 = "UPDATE x SET name = $1 WHERE id = $2 AND name = $1" |
|
|
278 |
|
* => $sql2 = "UPDATE x SET name = $1 WHERE id = $2 AND name = $1" |
213 |
279 |
*/ |
*/ |
214 |
|
function rg_sql_query_params($h, $sql, $params) |
|
|
280 |
|
function rg_sql_query_params_ignore($h, $sql, $params, $ignore, &$ignore_kicked) |
215 |
281 |
{ |
{ |
216 |
282 |
global $rg_sql_debug; |
global $rg_sql_debug; |
217 |
283 |
|
|
218 |
284 |
if ($rg_sql_debug > 0) |
if ($rg_sql_debug > 0) |
219 |
|
rg_log_enter("query_params: running [$sql] with [" . rg_array2string($params) . "]"); |
|
|
285 |
|
rg_log_enter('sql_query_params: sql=[' . $sql . ']' |
|
286 |
|
. ' params=[' . rg_array2string($params) . ']' |
|
287 |
|
. ' ignore=' . implode(',', $ignore)); |
220 |
288 |
|
|
221 |
289 |
$ret = FALSE; |
$ret = FALSE; |
222 |
290 |
while (1) { |
while (1) { |
|
... |
... |
function rg_sql_query_params($h, $sql, $params) |
241 |
309 |
//rg_log("new sql: $sql"); |
//rg_log("new sql: $sql"); |
242 |
310 |
//rg_log("params2: " . rg_array2string($params2)); |
//rg_log("params2: " . rg_array2string($params2)); |
243 |
311 |
|
|
244 |
|
$_s = microtime(TRUE); |
|
245 |
|
$res = @pg_query_params($db, $sql, $params2); |
|
246 |
|
$ret = rg_sql_query0($db, $sql, $res, $_s); |
|
|
312 |
|
$start_ts = microtime(TRUE); |
|
313 |
|
$r = @pg_send_query_params($db, $sql, $params2); |
|
314 |
|
$ret = rg_sql_query0($db, $sql, $r, $start_ts, $ignore, $ignore_kicked); |
247 |
315 |
break; |
break; |
248 |
316 |
} |
} |
249 |
317 |
|
|
|
... |
... |
function rg_sql_query_params($h, $sql, $params) |
252 |
320 |
return $ret; |
return $ret; |
253 |
321 |
} |
} |
254 |
322 |
|
|
|
323 |
|
function rg_sql_query_params($h, $sql, $params) |
|
324 |
|
{ |
|
325 |
|
$ignore = array(); |
|
326 |
|
return rg_sql_query_params_ignore($h, $sql, $params, |
|
327 |
|
$ignore, $ignore_kicked); |
|
328 |
|
} |
|
329 |
|
|
255 |
330 |
/* |
/* |
256 |
331 |
* Close database |
* Close database |
257 |
332 |
*/ |
*/ |
258 |
333 |
function rg_sql_close($h) |
function rg_sql_close($h) |
259 |
334 |
{ |
{ |
260 |
|
// TODO: why should I connect before close?! |
|
261 |
|
$db = rg_sql_open_nodelay($h); |
|
262 |
|
if ($db === FALSE) |
|
|
335 |
|
global $rg_sql_conn; |
|
336 |
|
|
|
337 |
|
if (!isset($rg_sql_conn[$h])) { |
|
338 |
|
rg_internal_error('Handler ' . $h . ' was not allocated!'); |
263 |
339 |
return FALSE; |
return FALSE; |
|
340 |
|
} |
|
341 |
|
|
|
342 |
|
if (!isset($rg_sql_conn[$h]['db'])) { |
|
343 |
|
// was not opened |
|
344 |
|
return TRUE; |
|
345 |
|
} |
264 |
346 |
|
|
265 |
|
return pg_close($db); |
|
|
347 |
|
$r = pg_close($rg_sql_conn[$h]['db']); |
|
348 |
|
if ($r === FALSE) |
|
349 |
|
return FALSE; |
|
350 |
|
|
|
351 |
|
unset($rg_sql_conn[$h]['db']); |
|
352 |
|
|
|
353 |
|
return TRUE; |
266 |
354 |
} |
} |
267 |
355 |
|
|
268 |
356 |
/* |
/* |
|
... |
... |
function rg_sql_rollback($h) |
357 |
445 |
* Test if a table exists |
* Test if a table exists |
358 |
446 |
* Returns FALSE on error, 0 if does not exists, 1 if exists |
* Returns FALSE on error, 0 if does not exists, 1 if exists |
359 |
447 |
*/ |
*/ |
360 |
|
function rg_sql_rel_exists($db, $rel) |
|
|
448 |
|
function rg_sql_rel_exists($h, $rel) |
361 |
449 |
{ |
{ |
362 |
450 |
$sql = "SELECT 1 FROM pg_class" |
$sql = "SELECT 1 FROM pg_class" |
363 |
451 |
. " WHERE relname = '" . $rel . "'"; |
. " WHERE relname = '" . $rel . "'"; |
364 |
|
$res = rg_sql_query($db, $sql); |
|
|
452 |
|
$res = rg_sql_query($h, $sql); |
365 |
453 |
if ($res === FALSE) |
if ($res === FALSE) |
366 |
454 |
return FALSE; |
return FALSE; |
367 |
455 |
|
|
|
... |
... |
function rg_sql_rel_exists($db, $rel) |
374 |
462 |
/* |
/* |
375 |
463 |
* Returns the fileds names of a table |
* Returns the fileds names of a table |
376 |
464 |
*/ |
*/ |
377 |
|
function rg_sql_fields($db, $table) |
|
|
465 |
|
function rg_sql_fields($h, $table) |
378 |
466 |
{ |
{ |
379 |
467 |
$params = array('table' => $table); |
$params = array('table' => $table); |
380 |
468 |
$sql = 'SELECT column_name FROM information_schema.columns' |
$sql = 'SELECT column_name FROM information_schema.columns' |
381 |
469 |
. ' WHERE table_name = @@table@@'; |
. ' WHERE table_name = @@table@@'; |
382 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
|
470 |
|
$res = rg_sql_query_params($h, $sql, $params); |
383 |
471 |
if ($res === FALSE) |
if ($res === FALSE) |
384 |
472 |
return FALSE; |
return FALSE; |
385 |
473 |
|
|
|
... |
... |
function rg_sql_fields($db, $table) |
393 |
481 |
return $ret; |
return $ret; |
394 |
482 |
} |
} |
395 |
483 |
|
|
|
484 |
|
/* |
|
485 |
|
* Returns the last error codes |
|
486 |
|
*/ |
|
487 |
|
function rg_sql_last_error_code($res) |
|
488 |
|
{ |
|
489 |
|
return @pg_result_error_field($res, PGSQL_DIAG_SQLSTATE); |
|
490 |
|
} |
|
491 |
|
|
396 |
492 |
?> |
?> |
File inc/user.inc.php changed (mode: 100644) (index 33db3df..e6d0a73) |
... |
... |
function rg_user_error() |
44 |
44 |
*/ |
*/ |
45 |
45 |
$rg_user_functions = array( |
$rg_user_functions = array( |
46 |
46 |
2000 => "rg_user_event_new", |
2000 => "rg_user_event_new", |
|
47 |
|
'user_event_new' => 'rg_user_event_new', |
47 |
48 |
2001 => "rg_user_event_login", |
2001 => "rg_user_event_login", |
|
49 |
|
'user_event_login' => "rg_user_event_login", |
48 |
50 |
2002 => "rg_user_event_notify_user", |
2002 => "rg_user_event_notify_user", |
49 |
51 |
2005 => "rg_user_event_rename", |
2005 => "rg_user_event_rename", |
50 |
52 |
2006 => "rg_user_link_by_name", |
2006 => "rg_user_link_by_name", |
|
... |
... |
function rg_user_insert_rename($db, $uid, $old_name) |
392 |
394 |
. " (" . rg_sql_error() . ")"); |
. " (" . rg_sql_error() . ")"); |
393 |
395 |
break; |
break; |
394 |
396 |
} |
} |
|
397 |
|
rg_sql_free_result($res); |
395 |
398 |
|
|
396 |
399 |
rg_cache_set("old_name::" . $old_name, $uid, RG_SOCKET_NO_WAIT); |
rg_cache_set("old_name::" . $old_name, $uid, RG_SOCKET_NO_WAIT); |
397 |
400 |
|
|
|
... |
... |
function rg_user_rename($db, $ui, $new_name) |
492 |
495 |
} |
} |
493 |
496 |
|
|
494 |
497 |
/* |
/* |
495 |
|
* Add/edit a user |
|
496 |
|
* If uid > 0 - edit, else, add |
|
|
498 |
|
* Helper for rg_user_edit |
497 |
499 |
*/ |
*/ |
498 |
|
function rg_user_edit($db, $d) |
|
|
500 |
|
function rg_user_edit_no_check($db, $d) |
499 |
501 |
{ |
{ |
500 |
|
rg_prof_start("user_edit"); |
|
501 |
|
rg_log_enter("user_edit: d: " . rg_array2string($d)); |
|
|
502 |
|
rg_prof_start('user_edit_no_check'); |
|
503 |
|
rg_log_enter('user_edit_no_check: d: ' . rg_array2string($d)); |
502 |
504 |
|
|
503 |
|
$ret = FALSE; |
|
|
505 |
|
$ret = array('ok' => 0, 'already_exists' => 0); |
504 |
506 |
while (1) { |
while (1) { |
505 |
507 |
$add = $d['uid'] == 0; |
$add = $d['uid'] == 0; |
506 |
508 |
|
|
507 |
|
if (rg_user_ok($d['username']) !== TRUE) |
|
508 |
|
break; |
|
509 |
|
|
|
510 |
|
// TODO: check rights |
|
511 |
|
// TODO - check if user is allowed to give passed rights |
|
512 |
|
|
|
513 |
|
if ($d['ask_for_email_confirmation'] == 1) |
|
514 |
|
$d['confirmed'] = 0; |
|
515 |
|
|
|
516 |
|
$update_pass = !empty($d['pass']); |
|
|
509 |
|
$update_pass = $add || !empty($d['pass']); |
517 |
510 |
if ($update_pass) { |
if ($update_pass) { |
518 |
511 |
if (strcmp($d['pass'], $d['pass2']) != 0) { |
if (strcmp($d['pass'], $d['pass2']) != 0) { |
519 |
|
rg_user_set_error("passwords are not the same"); |
|
|
512 |
|
$ret['errmsg'] = 'passwords are not the same'; |
|
513 |
|
break; |
|
514 |
|
} |
|
515 |
|
|
|
516 |
|
if (rg_user_pass_ok($d['pass']) !== TRUE) { |
|
517 |
|
$ret['errmsg'] = rg_user_error(); |
520 |
518 |
break; |
break; |
521 |
519 |
} |
} |
522 |
520 |
|
|
|
... |
... |
function rg_user_edit($db, $d) |
524 |
522 |
$d['pass_crypted'] = rg_user_pass($d['salt'], $d['pass']); |
$d['pass_crypted'] = rg_user_pass($d['salt'], $d['pass']); |
525 |
523 |
} |
} |
526 |
524 |
|
|
527 |
|
$d['itime'] = time(); |
|
|
525 |
|
// No need to keep them in memory |
|
526 |
|
unset($d['pass']); |
|
527 |
|
unset($d['pass2']); |
528 |
528 |
|
|
529 |
529 |
if ($add) { |
if ($add) { |
530 |
|
if (rg_user_pass_ok($d['pass']) !== TRUE) |
|
531 |
|
break; |
|
532 |
|
|
|
533 |
|
$d['suspended'] = 0; |
|
|
530 |
|
$d['itime'] = time(); |
|
531 |
|
if (!isset($d['suspended'])) |
|
532 |
|
$d['suspended'] = 0; |
534 |
533 |
$d['deleted'] = 0; |
$d['deleted'] = 0; |
535 |
534 |
$d['last_seen'] = 0; |
$d['last_seen'] = 0; |
536 |
535 |
$d['disk_used_mb'] = 0; |
$d['disk_used_mb'] = 0; |
537 |
|
$sql = "INSERT INTO users (username, realname, salt" |
|
538 |
|
. ", pass, email, itime" |
|
539 |
|
. ", is_admin, rights, session_time" |
|
540 |
|
. ", confirmed, confirm_token, plan_id" |
|
541 |
|
. ", suspended, last_seen, disk_used_mb" |
|
542 |
|
. ", deleted)" |
|
543 |
|
. " VALUES (@@username@@, @@realname@@, @@salt@@" |
|
544 |
|
. ", @@pass_crypted@@, @@email@@, @@itime@@" |
|
545 |
|
. ", @@is_admin@@, @@rights@@, @@session_time@@" |
|
546 |
|
. ", @@confirmed@@, @@confirm_token@@, @@plan_id@@" |
|
547 |
|
. ", @@suspended@@, @@last_seen@@" |
|
548 |
|
. ", @@disk_used_mb@@, @@deleted@@)" |
|
549 |
|
. " RETURNING uid"; |
|
|
536 |
|
$sql = 'INSERT INTO users (username, realname, salt' |
|
537 |
|
. ', pass, email, itime' |
|
538 |
|
. ', is_admin, rights, session_time' |
|
539 |
|
. ', confirmed, confirm_token, plan_id' |
|
540 |
|
. ', suspended, last_seen, disk_used_mb' |
|
541 |
|
. ', deleted)' |
|
542 |
|
. ' VALUES (@@username@@, @@realname@@, @@salt@@' |
|
543 |
|
. ', @@pass_crypted@@, @@email@@, @@itime@@' |
|
544 |
|
. ', @@is_admin@@, @@rights@@, @@session_time@@' |
|
545 |
|
. ', @@confirmed@@, @@confirm_token@@, @@plan_id@@' |
|
546 |
|
. ', @@suspended@@, @@last_seen@@' |
|
547 |
|
. ', @@disk_used_mb@@, @@deleted@@' |
|
548 |
|
. ')' |
|
549 |
|
. ' RETURNING uid'; |
|
550 |
|
|
|
551 |
|
$ignore = array(RG_SQL_UNIQUE_VIOLATION); |
550 |
552 |
} else { // edit |
} else { // edit |
551 |
553 |
$salt_pass_add = ""; |
$salt_pass_add = ""; |
552 |
554 |
if ($update_pass) |
if ($update_pass) |
553 |
|
$salt_pass_add = ", pass = @@pass_crypted@@" |
|
554 |
|
. ", salt = @@salt@@"; |
|
555 |
|
|
|
556 |
|
$sql = "UPDATE users" |
|
557 |
|
. " SET username = @@username@@" |
|
558 |
|
. ", realname = @@realname@@" |
|
559 |
|
. ", email = @@email@@" |
|
560 |
|
. ", is_admin = @@is_admin@@" |
|
561 |
|
. ", rights = @@rights@@" |
|
562 |
|
. ", session_time = @@session_time@@" |
|
563 |
|
. ", plan_id = @@plan_id@@" |
|
564 |
|
. ", confirmed = @@confirmed@@" |
|
565 |
|
. ", confirm_token = @@confirm_token@@" |
|
|
555 |
|
$salt_pass_add = ', pass = @@pass_crypted@@' |
|
556 |
|
. ', salt = @@salt@@'; |
|
557 |
|
|
|
558 |
|
$sql = 'UPDATE users' |
|
559 |
|
. ' SET username = @@username@@' |
|
560 |
|
. ', realname = @@realname@@' |
|
561 |
|
. ', email = @@email@@' |
|
562 |
|
. ', is_admin = @@is_admin@@' |
|
563 |
|
. ', rights = @@rights@@' |
|
564 |
|
. ', session_time = @@session_time@@' |
|
565 |
|
. ', plan_id = @@plan_id@@' |
|
566 |
|
. ', confirmed = @@confirmed@@' |
|
567 |
|
. ', confirm_token = @@confirm_token@@' |
566 |
568 |
. $salt_pass_add |
. $salt_pass_add |
567 |
|
. " WHERE uid = @@uid@@"; |
|
|
569 |
|
. ' WHERE uid = @@uid@@'; |
|
570 |
|
|
|
571 |
|
$ignore = array(); |
568 |
572 |
} |
} |
569 |
573 |
|
|
570 |
|
$res = rg_sql_query_params($db, $sql, $d); |
|
|
574 |
|
$res = rg_sql_query_params_ignore($db, $sql, $d, |
|
575 |
|
$ignore, $ignore_kicked); |
571 |
576 |
if ($res === FALSE) { |
if ($res === FALSE) { |
572 |
|
rg_user_set_error('cannot insert/update user info'); |
|
|
577 |
|
if (!$ignore_kicked) { |
|
578 |
|
$ret['errmsg'] = 'cannot insert/update user info'; |
|
579 |
|
break; |
|
580 |
|
} |
|
581 |
|
rg_log('DEBUG: username already present'); |
|
582 |
|
$ret['already_exists'] = 1; |
573 |
583 |
break; |
break; |
574 |
584 |
} |
} |
575 |
585 |
if ($add) { |
if ($add) { |
|
... |
... |
function rg_user_edit($db, $d) |
583 |
593 |
$d, RG_SOCKET_NO_WAIT); |
$d, RG_SOCKET_NO_WAIT); |
584 |
594 |
|
|
585 |
595 |
// we need to be able to send the welcome mail |
// we need to be able to send the welcome mail |
586 |
|
$d['ignore_confirmed'] = 1; |
|
|
596 |
|
$d2 = $d; |
|
597 |
|
$d2['ignore_confirmed'] = 1; |
587 |
598 |
|
|
588 |
599 |
$event = array( |
$event = array( |
589 |
|
'category' => 2000, |
|
|
600 |
|
'category' => 'user_event_new', |
590 |
601 |
'prio' => 50, |
'prio' => 50, |
591 |
|
'ui' => $d, |
|
|
602 |
|
'ui' => $d2, |
592 |
603 |
'base_url' => rg_base_url() |
'base_url' => rg_base_url() |
593 |
604 |
); |
); |
594 |
605 |
$r = rg_event_add($db, $event); |
$r = rg_event_add($db, $event); |
595 |
606 |
if ($r === FALSE) { |
if ($r === FALSE) { |
596 |
|
rg_user_set_error('cannot add event'); |
|
|
607 |
|
$ret['errmsg'] = 'cannot add event'; |
597 |
608 |
break; |
break; |
598 |
609 |
} |
} |
599 |
|
rg_event_signal_daemon("", 0); |
|
|
610 |
|
rg_event_signal_daemon('', 0); |
600 |
611 |
} else { // edit |
} else { // edit |
601 |
|
// else, we will overwrite the pass in cache |
|
602 |
|
if (!$update_pass) |
|
603 |
|
unset($d['pass']); |
|
604 |
|
unset($d['pass2']); // not needed in cache |
|
605 |
612 |
rg_cache_merge('user' . '::' . $d['uid'] |
rg_cache_merge('user' . '::' . $d['uid'] |
606 |
613 |
. '::' . 'info', $d, RG_SOCKET_NO_WAIT); |
. '::' . 'info', $d, RG_SOCKET_NO_WAIT); |
607 |
614 |
|
|
608 |
|
if ($d['ask_for_email_confirmation'] == 1) { |
|
|
615 |
|
if (isset($d['ask_for_email_confirmation']) |
|
616 |
|
&& ($d['ask_for_email_confirmation'] == 1)) { |
609 |
617 |
$r = rg_user_ask_for_email_confirmation($db, $d['uid']); |
$r = rg_user_ask_for_email_confirmation($db, $d['uid']); |
610 |
618 |
if ($r === FALSE) { |
if ($r === FALSE) { |
611 |
|
rg_user_set_error('cannot add event'); |
|
|
619 |
|
$ret['errmsg'] = 'cannot add event'; |
612 |
620 |
break; |
break; |
613 |
621 |
} |
} |
614 |
622 |
} |
} |
|
... |
... |
function rg_user_edit($db, $d) |
616 |
624 |
|
|
617 |
625 |
// TODO: should we cache here the user_by_uid and user_by_name |
// TODO: should we cache here the user_by_uid and user_by_name |
618 |
626 |
|
|
619 |
|
$ret = $d['uid']; |
|
|
627 |
|
$ret['ui'] = $d; |
|
628 |
|
$ret['ok'] = 1; |
|
629 |
|
break; |
|
630 |
|
} |
|
631 |
|
|
|
632 |
|
rg_log_exit(); |
|
633 |
|
rg_prof_end('user_edit_no_check'); |
|
634 |
|
return $ret; |
|
635 |
|
} |
|
636 |
|
|
|
637 |
|
/* |
|
638 |
|
* Add/edit a user |
|
639 |
|
* If uid > 0 - edit, else, add |
|
640 |
|
*/ |
|
641 |
|
function rg_user_edit($db, $d) |
|
642 |
|
{ |
|
643 |
|
rg_prof_start("user_edit"); |
|
644 |
|
rg_log_enter("user_edit: d: " . rg_array2string($d)); |
|
645 |
|
|
|
646 |
|
$ret = FALSE; |
|
647 |
|
while (1) { |
|
648 |
|
if (rg_user_ok($d['username']) !== TRUE) |
|
649 |
|
break; |
|
650 |
|
|
|
651 |
|
// TODO: check rights |
|
652 |
|
// TODO - check if user is allowed to give passed rights |
|
653 |
|
|
|
654 |
|
if (isset($d['ask_for_email_confirmation']) |
|
655 |
|
&& ($d['ask_for_email_confirmation'] == 1)) |
|
656 |
|
$d['confirmed'] = 0; |
|
657 |
|
|
|
658 |
|
$r = rg_user_edit_no_check($db, $d); |
|
659 |
|
if ($r['ok'] !== 1) { |
|
660 |
|
rg_user_set_error($r['errmsg']); |
|
661 |
|
break; |
|
662 |
|
} |
|
663 |
|
|
|
664 |
|
$ret = $r['ui']['uid']; |
620 |
665 |
break; |
break; |
621 |
666 |
} |
} |
622 |
667 |
|
|
|
... |
... |
function rg_user_auto_login($db, $uid, $lock_ip, $domain, &$ui) |
943 |
988 |
} |
} |
944 |
989 |
|
|
945 |
990 |
/* |
/* |
946 |
|
* Test if login is OK |
|
|
991 |
|
* Helper for rg_user_login_by_user_pass for db |
947 |
992 |
*/ |
*/ |
948 |
|
function rg_user_login_by_user_pass($db, $user, $pass, $login_token, $lock_ip, |
|
949 |
|
$domain, &$ui) |
|
|
993 |
|
function rg_user_login_by_user_pass_db($db, $user, $pass, $login_token, |
|
994 |
|
$lock_ip, $domain, &$ui) |
950 |
995 |
{ |
{ |
951 |
996 |
global $rg_account_email_confirm; |
global $rg_account_email_confirm; |
952 |
997 |
|
|
953 |
|
rg_prof_start('user_login_by_user_pass'); |
|
954 |
|
rg_log_enter('user_login_by_user_pass: user=' . $user |
|
|
998 |
|
rg_prof_start('user_login_by_user_pass_db'); |
|
999 |
|
rg_log_enter('user_login_by_user_pass_db: user=' . $user |
955 |
1000 |
. ' login_token=' . $login_token . ' lock_ip=' . $lock_ip |
. ' login_token=' . $login_token . ' lock_ip=' . $lock_ip |
956 |
1001 |
. ' domain=' . $domain); |
. ' domain=' . $domain); |
957 |
1002 |
|
|
|
... |
... |
function rg_user_login_by_user_pass($db, $user, $pass, $login_token, $lock_ip, |
959 |
1004 |
|
|
960 |
1005 |
$ret = FALSE; |
$ret = FALSE; |
961 |
1006 |
while (1) { |
while (1) { |
962 |
|
if (empty($user) || empty($pass)) { |
|
963 |
|
rg_user_set_error("invalid user, pass or login token"); |
|
964 |
|
rg_log("user or pass are empty"); |
|
965 |
|
break; |
|
966 |
|
} |
|
967 |
|
|
|
968 |
1007 |
$ui0 = rg_user_info($db, 0, $user, ""); |
$ui0 = rg_user_info($db, 0, $user, ""); |
969 |
1008 |
if ($ui0['ok'] != 1) |
if ($ui0['ok'] != 1) |
970 |
1009 |
break; |
break; |
971 |
1010 |
if ($ui0['exists'] != 1) { |
if ($ui0['exists'] != 1) { |
972 |
|
rg_user_set_error("invalid user, pass or login token"); |
|
973 |
|
rg_log("user doesn't exists"); |
|
974 |
|
break; |
|
975 |
|
} |
|
976 |
|
|
|
977 |
|
if ($ui0['deleted'] > 0) { |
|
978 |
1011 |
rg_user_set_error('invalid user, pass or login token'); |
rg_user_set_error('invalid user, pass or login token'); |
979 |
|
rg_log('account is deleted'); |
|
980 |
|
break; |
|
981 |
|
} |
|
982 |
|
|
|
983 |
|
if ($ui0['suspended'] > 0) { |
|
984 |
|
rg_user_set_error("invalid user, pass or login token"); |
|
985 |
|
rg_log("account is suspended"); |
|
|
1012 |
|
rg_log('user doesn\'t exists'); |
986 |
1013 |
break; |
break; |
987 |
1014 |
} |
} |
988 |
1015 |
|
|
|
... |
... |
function rg_user_login_by_user_pass($db, $user, $pass, $login_token, $lock_ip, |
999 |
1026 |
break; |
break; |
1000 |
1027 |
} |
} |
1001 |
1028 |
|
|
1002 |
|
$vi = rg_totp_verify_any($db, $ui0['uid'], $login_token); |
|
|
1029 |
|
$ui = $ui0; |
|
1030 |
|
$ret = TRUE; |
|
1031 |
|
break; |
|
1032 |
|
} |
|
1033 |
|
|
|
1034 |
|
rg_log_exit(); |
|
1035 |
|
rg_prof_end('user_login_by_user_pass_db'); |
|
1036 |
|
return $ret; |
|
1037 |
|
} |
|
1038 |
|
|
|
1039 |
|
/* |
|
1040 |
|
* Authorize a user |
|
1041 |
|
*/ |
|
1042 |
|
function rg_user_login_by_user_pass($db, $user, $pass, $login_token, |
|
1043 |
|
$lock_ip, $domain, &$ui) |
|
1044 |
|
{ |
|
1045 |
|
global $rg_login_functions; |
|
1046 |
|
|
|
1047 |
|
// TODO: what about $ui - for ldap will not have some elements. |
|
1048 |
|
// Should we fake them? |
|
1049 |
|
|
|
1050 |
|
rg_prof_start('user_login_by_user_pass'); |
|
1051 |
|
rg_log_enter('user_login_by_user_pass: user=' . $user |
|
1052 |
|
. ' login_token=' . $login_token . ' lock_ip=' . $lock_ip |
|
1053 |
|
. ' domain=' . $domain); |
|
1054 |
|
|
|
1055 |
|
$ui = rg_user_empty(); |
|
1056 |
|
|
|
1057 |
|
$ret = array(); |
|
1058 |
|
$ret['ok'] = 0; |
|
1059 |
|
while (1) { |
|
1060 |
|
if (empty($user) || empty($pass)) { |
|
1061 |
|
rg_log("user or pass are empty"); |
|
1062 |
|
$ret['errmsg'] = 'invalid user, pass or login token'; |
|
1063 |
|
break; |
|
1064 |
|
} |
|
1065 |
|
|
|
1066 |
|
while (1) { |
|
1067 |
|
$r = rg_user_login_by_user_pass_db($db, $user, $pass, |
|
1068 |
|
$login_token, $lock_ip, $domain, $ui); |
|
1069 |
|
if ($r === TRUE) |
|
1070 |
|
break; |
|
1071 |
|
|
|
1072 |
|
$ret['errmsg'] = rg_user_error(); |
|
1073 |
|
|
|
1074 |
|
// Try external authentication |
|
1075 |
|
foreach ($rg_login_functions as $funcs) { |
|
1076 |
|
$r = $funcs['login']($db, $user, $pass, $ui); |
|
1077 |
|
if ($r['ok'] === 1) { |
|
1078 |
|
unset($ret['errmsg']); |
|
1079 |
|
$post = $r['post']; |
|
1080 |
|
break; |
|
1081 |
|
} |
|
1082 |
|
} |
|
1083 |
|
if (isset($ret['errmsg'])) |
|
1084 |
|
break; |
|
1085 |
|
|
|
1086 |
|
// We found a good user/pass combination |
|
1087 |
|
rg_log_ml('DEBUG: post: ' . print_r($post, TRUE)); |
|
1088 |
|
rg_log_ml('DEBUG: ui returned by login callback: ' . print_r($ui, TRUE)); |
|
1089 |
|
|
|
1090 |
|
$check_for_changes = TRUE; |
|
1091 |
|
if ($ui['uid'] == 0) { |
|
1092 |
|
// User found, but not in 'users' table. |
|
1093 |
|
// We update the table and call the callback |
|
1094 |
|
// to set uid into external auth table. |
|
1095 |
|
|
|
1096 |
|
rg_log('DEBUG: user not in \'users\' table (ui[uid] 0), add it'); |
|
1097 |
|
$r = rg_user_edit_no_check($db, $ui); |
|
1098 |
|
if ($r['ok'] !== 1) { |
|
1099 |
|
if ($r['already_exists'] == 0) { |
|
1100 |
|
$ret['errmsg'] = $r['errmsg']; |
|
1101 |
|
break; |
|
1102 |
|
} |
|
1103 |
|
|
|
1104 |
|
rg_log('DEBUG: user is already present' |
|
1105 |
|
. '; lookup by username'); |
|
1106 |
|
$ui = rg_user_info($db, 0, $ui['username'], ''); |
|
1107 |
|
if ($ui['ok'] !== 1) { |
|
1108 |
|
$ret['errmsg'] = rg_user_error(); |
|
1109 |
|
break; |
|
1110 |
|
} |
|
1111 |
|
} else { |
|
1112 |
|
$ui['uid'] = $r['ui']['uid']; |
|
1113 |
|
$check_for_changes = FALSE; |
|
1114 |
|
} |
|
1115 |
|
|
|
1116 |
|
// This will update external auth cache uid. |
|
1117 |
|
if (isset($funcs['post_login'])) { |
|
1118 |
|
$r = $funcs['post_login']($db, |
|
1119 |
|
$ui['uid'], $post); |
|
1120 |
|
// We will not return an error here |
|
1121 |
|
if ($r['ok'] !== 1) |
|
1122 |
|
rg_log('post_login function' |
|
1123 |
|
. ' returned error: ' |
|
1124 |
|
. $r['errmsg']); |
|
1125 |
|
} |
|
1126 |
|
} else { |
|
1127 |
|
// User found, but some fields may have old |
|
1128 |
|
// values and we may need to update 'users'. |
|
1129 |
|
|
|
1130 |
|
rg_log('DEBUG: user exists in db (ui[uid]!=0), load info'); |
|
1131 |
|
$ui = rg_user_info($db, $ui['uid'], '', ''); |
|
1132 |
|
if ($ui['ok'] !== 1) { |
|
1133 |
|
$ret['errmsg'] = rg_user_error(); |
|
1134 |
|
break; |
|
1135 |
|
} |
|
1136 |
|
} |
|
1137 |
|
|
|
1138 |
|
// Some fields could change |
|
1139 |
|
$do_update = FALSE; |
|
1140 |
|
while (1) { |
|
1141 |
|
if (!$check_for_changes) |
|
1142 |
|
break; |
|
1143 |
|
|
|
1144 |
|
if (strcmp($ui['username'], $post['username']) != 0) { |
|
1145 |
|
rg_log('DEBUG: different username: ' . $ui['username'] . ' != ' . $post['username']); |
|
1146 |
|
$ui['username'] = $post['username']; |
|
1147 |
|
$do_update = TRUE; |
|
1148 |
|
break; |
|
1149 |
|
} |
|
1150 |
|
|
|
1151 |
|
if (strcmp($ui['email'], $post['mail']) != 0) { |
|
1152 |
|
rg_log('DEBUG: different mail'); |
|
1153 |
|
$ui['email'] = $post['mail']; |
|
1154 |
|
$do_update = TRUE; |
|
1155 |
|
break; |
|
1156 |
|
} |
|
1157 |
|
|
|
1158 |
|
if (strcmp($ui['realname'], $post['realname']) != 0) { |
|
1159 |
|
rg_log('DEBUG: different realname'); |
|
1160 |
|
$ui['realname'] = $post['realname']; |
|
1161 |
|
$do_update = TRUE; |
|
1162 |
|
break; |
|
1163 |
|
} |
|
1164 |
|
|
|
1165 |
|
if (strcmp($ui['pass'], $post['password']) != 0) { |
|
1166 |
|
rg_log('DEBUG: different passwords'); |
|
1167 |
|
$ui['pass'] = $post['password']; |
|
1168 |
|
$ui['pass2'] = $post['password']; |
|
1169 |
|
$do_update = TRUE; |
|
1170 |
|
break; |
|
1171 |
|
} |
|
1172 |
|
|
|
1173 |
|
// TODO: expiration? |
|
1174 |
|
// TODO: plan_id will change when we will edit |
|
1175 |
|
// the ldap server info. Same with is_admin. |
|
1176 |
|
// Same with 'prio'. |
|
1177 |
|
|
|
1178 |
|
break; |
|
1179 |
|
} |
|
1180 |
|
if ($do_update) { |
|
1181 |
|
rg_log('DEBUG: desync between sql and ldap'); |
|
1182 |
|
|
|
1183 |
|
// If we do not have pass2, we do not want |
|
1184 |
|
// to change the password. |
|
1185 |
|
if (!isset($ui['pass2'])) |
|
1186 |
|
unset($ui['pass']); |
|
1187 |
|
|
|
1188 |
|
$r = rg_user_edit_no_check($db, $ui); |
|
1189 |
|
if ($r['ok'] !== 1) { |
|
1190 |
|
$ret['errmsg'] = $r['errmsg']; |
|
1191 |
|
break; |
|
1192 |
|
} |
|
1193 |
|
} |
|
1194 |
|
|
|
1195 |
|
break; |
|
1196 |
|
} |
|
1197 |
|
if (isset($ret['errmsg'])) |
|
1198 |
|
break; |
|
1199 |
|
|
|
1200 |
|
if ($ui['deleted'] > 0) { |
|
1201 |
|
$ret['errmsg'] = 'invalid user, pass or login token'; |
|
1202 |
|
rg_log('account is deleted'); |
|
1203 |
|
break; |
|
1204 |
|
} |
|
1205 |
|
|
|
1206 |
|
if ($ui['suspended'] > 0) { |
|
1207 |
|
$ret['errmsg'] = 'invalid user, pass or login token'; |
|
1208 |
|
rg_log('account is suspended'); |
|
1209 |
|
break; |
|
1210 |
|
} |
|
1211 |
|
|
|
1212 |
|
$vi = rg_totp_verify_any($db, $ui['uid'], $login_token); |
1003 |
1213 |
if ($vi['ok'] != 1) { |
if ($vi['ok'] != 1) { |
1004 |
|
rg_user_set_error('login token error: ' . rg_totp_error()); |
|
|
1214 |
|
$ret['errmsg'] = 'login token error: ' . rg_totp_error(); |
1005 |
1215 |
break; |
break; |
1006 |
1216 |
} |
} |
1007 |
1217 |
//rg_log_ml('DEBUG: vi: ' . print_r($vi, TRUE)); |
//rg_log_ml('DEBUG: vi: ' . print_r($vi, TRUE)); |
1008 |
1218 |
if (($vi['enrolled'] == 1) && ($vi['token_valid'] != 1)) { |
if (($vi['enrolled'] == 1) && ($vi['token_valid'] != 1)) { |
1009 |
|
rg_user_set_error('invalid user, pass or login token'); |
|
|
1219 |
|
$ret['errmsg'] = 'invalid user, pass or login token'; |
1010 |
1220 |
rg_log('invalid token'); |
rg_log('invalid token'); |
1011 |
1221 |
break; |
break; |
1012 |
1222 |
} |
} |
1013 |
1223 |
|
|
1014 |
1224 |
$event = array( |
$event = array( |
1015 |
|
'category' => 2001, |
|
|
1225 |
|
'category' => 'user_event_login', |
1016 |
1226 |
'prio' => 100, |
'prio' => 100, |
1017 |
|
'ui' => $ui0, |
|
|
1227 |
|
'ui' => $ui, |
1018 |
1228 |
'itime' => time()); |
'itime' => time()); |
1019 |
1229 |
$r = rg_event_add($db, $event); |
$r = rg_event_add($db, $event); |
1020 |
1230 |
if ($r !== TRUE) { |
if ($r !== TRUE) { |
1021 |
|
rg_user_set_error('internal error; try again later'); |
|
|
1231 |
|
$ret['errmsg'] = 'internal error; try again later'; |
1022 |
1232 |
break; |
break; |
1023 |
1233 |
} |
} |
1024 |
1234 |
rg_event_signal_daemon('', 0); |
rg_event_signal_daemon('', 0); |
1025 |
1235 |
|
|
1026 |
|
$ui = $ui0; |
|
1027 |
1236 |
rg_user_auto_login($db, $ui['uid'], $lock_ip, $domain, $ui); |
rg_user_auto_login($db, $ui['uid'], $lock_ip, $domain, $ui); |
1028 |
1237 |
|
|
1029 |
|
$ret = TRUE; |
|
|
1238 |
|
$ret['ok'] = 1; |
1030 |
1239 |
break; |
break; |
1031 |
1240 |
} |
} |
1032 |
1241 |
|
|
1033 |
1242 |
rg_log_exit(); |
rg_log_exit(); |
1034 |
|
rg_prof_start("user_login_by_user_pass"); |
|
|
1243 |
|
rg_prof_end('user_login_by_user_pass'); |
1035 |
1244 |
return $ret; |
return $ret; |
1036 |
1245 |
} |
} |
1037 |
1246 |
|
|
|
... |
... |
function rg_user_edit_high_level($db, &$rg) |
1649 |
1858 |
else |
else |
1650 |
1859 |
$ui['tos'] = rg_var_uint('tos'); |
$ui['tos'] = rg_var_uint('tos'); |
1651 |
1860 |
|
|
1652 |
|
$ui['ask_for_email_confirmation'] = 0; |
|
1653 |
1861 |
$ui['confirm_token'] = rg_id(20); |
$ui['confirm_token'] = rg_id(20); |
1654 |
1862 |
if ($rg['target_ui']['uid'] > 0) { |
if ($rg['target_ui']['uid'] > 0) { |
1655 |
1863 |
if (strcasecmp($rg['target_ui']['email'], $ui['email']) != 0) { |
if (strcasecmp($rg['target_ui']['email'], $ui['email']) != 0) { |
|
... |
... |
function rg_user_edit_high_level($db, &$rg) |
1719 |
1927 |
|
|
1720 |
1928 |
if ($load_form) { |
if ($load_form) { |
1721 |
1929 |
$rg = array_merge($rg, $ui); |
$rg = array_merge($rg, $ui); |
1722 |
|
$rg['HTML:select_plan'] = rg_plan_select($db, $ui['plan_id']); |
|
|
1930 |
|
$rg['HTML:select_plan'] = rg_plan_select($db, 'plan_id', |
|
1931 |
|
$ui['plan_id']); |
1723 |
1932 |
$rg['HTML:checkbox_rights'] = rg_rights_checkboxes("user", |
$rg['HTML:checkbox_rights'] = rg_rights_checkboxes("user", |
1724 |
1933 |
"rights", $ui['rights']); |
"rights", $ui['rights']); |
1725 |
1934 |
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
$rg['HTML:errmsg'] = rg_template_errmsg($errmsg); |
|
... |
... |
function rg_process_input($content_length, $content_encoding, &$err) |
1897 |
2106 |
// TODO: Sadly, we are not able to do the streaming! |
// TODO: Sadly, we are not able to do the streaming! |
1898 |
2107 |
// It is not available to php-fpm! |
// It is not available to php-fpm! |
1899 |
2108 |
|
|
1900 |
|
rg_git_info_pack("\x02", 'We could not process' |
|
1901 |
|
. ' the data (chunked).'); |
|
1902 |
|
|
|
|
2109 |
|
rg_git_info_pack("\x02", 'We could not process' |
|
2110 |
|
. ' the data (chunked).'); |
1903 |
2111 |
|
|
1904 |
2112 |
$err = 'You are trying to push chunked encoding data' |
$err = 'You are trying to push chunked encoding data' |
1905 |
2113 |
. ' but php-fpm does not support it.' . "\n" |
. ' but php-fpm does not support it.' . "\n" |
|
... |
... |
function rg_user_http_git($db, $rg, $paras) |
2046 |
2254 |
$rg['login_ui'], $prefix, $user, $repo, $service); |
$rg['login_ui'], $prefix, $user, $repo, $service); |
2047 |
2255 |
rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE)); |
rg_log_ml('DEBUG: repo_fetch_push_helper: ' . print_r($r, TRUE)); |
2048 |
2256 |
if ($r['ok'] !== 1) { |
if ($r['ok'] !== 1) { |
2049 |
|
rg_log('DEBUG: set errror: ' . $r['error']); |
|
2050 |
|
header('X-Rocketgit-Error: ' . $r['error']); |
|
|
2257 |
|
rg_log('DEBUG: set errror: ' . $r['errmsg']); |
|
2258 |
|
header('X-Rocketgit-Error: ' . $r['errmsg']); |
2051 |
2259 |
|
|
2052 |
2260 |
if (isset($r['owner_ui'])) { |
if (isset($r['owner_ui'])) { |
2053 |
2261 |
if ($r['owner_ui']['ok'] != 1) { |
if ($r['owner_ui']['ok'] != 1) { |
|
... |
... |
function rg_user_http_git($db, $rg, $paras) |
2089 |
2297 |
. ' realm="Use empty user if you have no account"'); |
. ' realm="Use empty user if you have no account"'); |
2090 |
2298 |
echo 'RocketGit: Info: == Welcome to RocketGit! ==' . "\n"; |
echo 'RocketGit: Info: == Welcome to RocketGit! ==' . "\n"; |
2091 |
2299 |
echo 'RocketGit: Info: you are connecting from IP ' . $rg['ip'] . '.' . "\n"; |
echo 'RocketGit: Info: you are connecting from IP ' . $rg['ip'] . '.' . "\n"; |
2092 |
|
echo 'RocketGit: Error: ' . $r['error'] . '!'; |
|
|
2300 |
|
echo 'RocketGit: Error: ' . $r['errmsg'] . '!'; |
2093 |
2301 |
break; |
break; |
2094 |
2302 |
} |
} |
2095 |
2303 |
|
|
2096 |
2304 |
rg_log('DEBUG: push_allowed=' . $r['push_allowed'] |
rg_log('DEBUG: push_allowed=' . $r['push_allowed'] |
2097 |
2305 |
. ' empty_user=' . ($empty_user ? 'yes' : 'no') |
. ' empty_user=' . ($empty_user ? 'yes' : 'no') |
2098 |
|
. ' authd=' . ($authd === TRUE ? 'yes' : 'no') |
|
|
2306 |
|
. ' authd=' . ($authd['ok'] === 1 ? 'yes' : 'no') |
2099 |
2307 |
. ' exists=' . $auth_ui['exists'] |
. ' exists=' . $auth_ui['exists'] |
2100 |
2308 |
. ' push=' . $r['push']); |
. ' push=' . $r['push']); |
2101 |
2309 |
if (($r['push'] === 1) && ($r['push_allowed'] !== 1)) { |
if (($r['push'] === 1) && ($r['push_allowed'] !== 1)) { |
|
... |
... |
function rg_user_http_git($db, $rg, $paras) |
2104 |
2312 |
// the user to try again. If user is not correct, |
// the user to try again. If user is not correct, |
2105 |
2313 |
// we will go on with anon push access. |
// we will go on with anon push access. |
2106 |
2314 |
if ($empty_user |
if ($empty_user |
2107 |
|
|| (($authd === FALSE) && ($auth_ui['exists'] == 1))) { |
|
|
2315 |
|
|| (($authd['ok'] !== 1) && ($auth_ui['exists'] == 1))) { |
2108 |
2316 |
rg_log('DEBUG: send 401'); |
rg_log('DEBUG: send 401'); |
2109 |
2317 |
header($protocol . ' 401 Unauthorized status'); |
header($protocol . ' 401 Unauthorized status'); |
2110 |
2318 |
header('WWW-Authenticate: Basic' |
header('WWW-Authenticate: Basic' |
File inc/util.inc.php changed (mode: 100644) (index 41d439d..70d954e) |
... |
... |
register_shutdown_function("rg_error_shutdown"); |
7 |
7 |
|
|
8 |
8 |
define('RG_SOCKET_NO_WAIT', 0x01); |
define('RG_SOCKET_NO_WAIT', 0x01); |
9 |
9 |
|
|
|
10 |
|
if (!isset($rg_util_debug)) |
|
11 |
|
$rg_util_debug = FALSE; |
|
12 |
|
|
10 |
13 |
$rg_util_error = ""; |
$rg_util_error = ""; |
11 |
14 |
|
|
12 |
15 |
function rg_util_set_error($str) |
function rg_util_set_error($str) |
|
... |
... |
function rg_exec($cmd, $input, $cb_stdout, $cb_stderr) |
1189 |
1192 |
return $ret; |
return $ret; |
1190 |
1193 |
} |
} |
1191 |
1194 |
|
|
|
1195 |
|
/* |
|
1196 |
|
* This will replace rg_exec function |
|
1197 |
|
*/ |
|
1198 |
|
function rg_exec2(&$a) |
|
1199 |
|
{ |
|
1200 |
|
global $rg_util_debug; |
|
1201 |
|
|
|
1202 |
|
rg_prof_start('exec2'); |
|
1203 |
|
rg_log_enter('exec2'); |
|
1204 |
|
|
|
1205 |
|
$rg_util_debug && |
|
1206 |
|
rg_log_ml('DEBUG: a: ' . print_r($a, TRUE)); |
|
1207 |
|
|
|
1208 |
|
// some status initialization |
|
1209 |
|
$s = array(); |
|
1210 |
|
foreach ($a['cmds'] as $cmd => &$info) { |
|
1211 |
|
if (!isset($info['restart_delay'])) |
|
1212 |
|
$info['restart_delay'] = 0; |
|
1213 |
|
if (!isset($info['idle_time'])) |
|
1214 |
|
$info['idle_time'] = 5; |
|
1215 |
|
|
|
1216 |
|
$info['needs_start'] = TRUE; |
|
1217 |
|
$info['needs_stop'] = FALSE; |
|
1218 |
|
$info['last_failure'] = 0; |
|
1219 |
|
if (!isset($info['out_buf'])) |
|
1220 |
|
$info['out_buf'] = ''; |
|
1221 |
|
$info['in_buf'] = ''; |
|
1222 |
|
$info['err_buf'] = ''; |
|
1223 |
|
$info['done'] = FALSE; |
|
1224 |
|
$info['last_activity'] = 0; |
|
1225 |
|
$info['stopped'] = TRUE; |
|
1226 |
|
$info['closed'] = array(1 => 0, 2 => 0); |
|
1227 |
|
} |
|
1228 |
|
|
|
1229 |
|
$ret = array(); |
|
1230 |
|
$ret['ok'] = 0; |
|
1231 |
|
while (1) { |
|
1232 |
|
// check if all commands are started |
|
1233 |
|
$now = time(); |
|
1234 |
|
$rx = array(); $wx = array(); |
|
1235 |
|
$lut = array(); |
|
1236 |
|
$done = TRUE; |
|
1237 |
|
foreach ($a['cmds'] as $index => &$info) { |
|
1238 |
|
if (($info['closed'][1] == 1) && ($info['closed'][2] == 1)) { |
|
1239 |
|
$rg_util_debug && rg_log('DEBUG: Both in streams are closed.'); |
|
1240 |
|
$info['needs_stop'] = TRUE; |
|
1241 |
|
} |
|
1242 |
|
|
|
1243 |
|
if ($info['needs_stop'] == TRUE) { |
|
1244 |
|
$rg_util_debug && |
|
1245 |
|
rg_log('DEBUG: index ' . $index . ' needs stop!'); |
|
1246 |
|
|
|
1247 |
|
$info['ps'] = @proc_get_status($info['a']); |
|
1248 |
|
$rg_util_debug && |
|
1249 |
|
rg_log_ml('DEBUG: info[ps][' . $index . ']: ' |
|
1250 |
|
. print_r($info['ps'], TRUE)); |
|
1251 |
|
|
|
1252 |
|
if ($info['ps']['running'] === FALSE) { |
|
1253 |
|
$ec = $info['ps']['exitcode']; |
|
1254 |
|
} else { |
|
1255 |
|
for ($i = 0; $i < 3; $i++) |
|
1256 |
|
if (isset($info['pipes'][$i])) |
|
1257 |
|
fclose($info['pipes'][$i]); |
|
1258 |
|
|
|
1259 |
|
$err = @proc_close($info['a']); |
|
1260 |
|
if ($err != 0) |
|
1261 |
|
$rg_util_debug && |
|
1262 |
|
rg_log('DEBUG: proc_close returned ' . $err); |
|
1263 |
|
$ec = 0; /* we are force closing program */ |
|
1264 |
|
} |
|
1265 |
|
|
|
1266 |
|
if (isset($info['cb_finish'])) |
|
1267 |
|
$info['cb_finish']($index, $info, $ec); |
|
1268 |
|
|
|
1269 |
|
unset($info['pipes']); |
|
1270 |
|
unset($info['a']); |
|
1271 |
|
|
|
1272 |
|
$info['needs_stop'] = FALSE; |
|
1273 |
|
$info['stopped'] = TRUE; |
|
1274 |
|
|
|
1275 |
|
if (isset($info['restart_delay'])) { |
|
1276 |
|
$rg_util_debug && |
|
1277 |
|
rg_log('DEBUG: index ' . $index . ' has no restart flag => done = TRUE'); |
|
1278 |
|
$info['done'] = TRUE; |
|
1279 |
|
} |
|
1280 |
|
} |
|
1281 |
|
|
|
1282 |
|
$rg_util_debug && |
|
1283 |
|
rg_log('DEBUG: index=' . $index |
|
1284 |
|
. ' done=' . ($info['done'] === TRUE ? 'true' : 'false')); |
|
1285 |
|
if ($info['done']) |
|
1286 |
|
continue; |
|
1287 |
|
|
|
1288 |
|
$done = FALSE; |
|
1289 |
|
|
|
1290 |
|
if ($info['needs_start'] == TRUE) { |
|
1291 |
|
$done = FALSE; |
|
1292 |
|
|
|
1293 |
|
if ($info['last_failure'] + $info['restart_delay'] > $now) |
|
1294 |
|
continue; |
|
1295 |
|
|
|
1296 |
|
$rg_util_debug && |
|
1297 |
|
rg_log('DEBUG: Running [' . $info['cmd'] . ']'); |
|
1298 |
|
$desc = array( |
|
1299 |
|
0 => array("pipe", "r"), |
|
1300 |
|
1 => array('pipe', 'w'), |
|
1301 |
|
2 => array("pipe", "w") |
|
1302 |
|
); |
|
1303 |
|
|
|
1304 |
|
$info['a'] = proc_open($info['cmd'], $desc, $info['pipes']); |
|
1305 |
|
if ($info['a'] === FALSE) { |
|
1306 |
|
$info['last_errmsg'] = 'cannot do proc_open'; |
|
1307 |
|
if (isset($info['cb_error'])) |
|
1308 |
|
$info['cb_error']($index, $info, $info['last_errmsg']); |
|
1309 |
|
$info['last_failure'] = $now; |
|
1310 |
|
continue; |
|
1311 |
|
} |
|
1312 |
|
|
|
1313 |
|
$rg_util_debug && |
|
1314 |
|
rg_log_ml('DEBUG: proc_open pipes: ' |
|
1315 |
|
. print_r($info['pipes'], TRUE)); |
|
1316 |
|
$info['needs_start'] = FALSE; |
|
1317 |
|
$info['start_ts'] = time(); |
|
1318 |
|
$info['stopped'] = FALSE; |
|
1319 |
|
$info['last_errmsg'] = ''; |
|
1320 |
|
$info['closed'][1] = 0; |
|
1321 |
|
$info['closed'][2] = 0; |
|
1322 |
|
} |
|
1323 |
|
|
|
1324 |
|
if ($info['stopped']) { |
|
1325 |
|
$rg_util_debug && |
|
1326 |
|
rg_log('DEBUG: index ' . $index. ' is stopped'); |
|
1327 |
|
continue; |
|
1328 |
|
} |
|
1329 |
|
|
|
1330 |
|
// Check idle |
|
1331 |
|
if (isset($info['cb_idle']) |
|
1332 |
|
&& ($info['idle_time'] > 0) |
|
1333 |
|
&& ($info['last_activity'] > 0) |
|
1334 |
|
&& ($info['last_activity'] + $info['idle_time'] <= time())) { |
|
1335 |
|
$rg_util_debug && |
|
1336 |
|
rg_log('DEBUG: IDLE: ' . $index |
|
1337 |
|
. ' last_activity=' . $info['last_activity'] |
|
1338 |
|
. ' now=' . time()); |
|
1339 |
|
$info['cb_idle']($index, $info); |
|
1340 |
|
} |
|
1341 |
|
|
|
1342 |
|
if ($info['closed'][1] == 0) $rx[] = $info['pipes'][1]; |
|
1343 |
|
if ($info['closed'][2] == 0) $rx[] = $info['pipes'][2]; |
|
1344 |
|
|
|
1345 |
|
if (isset($info['cb_output']) || !empty($info['out_buf'])) { |
|
1346 |
|
$rg_util_debug && |
|
1347 |
|
rg_log('DEBUG: We have cb_output or data in out_buf, enable write notification!'); |
|
1348 |
|
$wx[] = $info['pipes'][0]; |
|
1349 |
|
} |
|
1350 |
|
|
|
1351 |
|
for ($i = 0; $i <= 2; $i++) { |
|
1352 |
|
$k = intval($info['pipes'][$i]); |
|
1353 |
|
$lut[$k] = array('index' => $index, 'stream' => $i); |
|
1354 |
|
} |
|
1355 |
|
} |
|
1356 |
|
if ($done) { |
|
1357 |
|
$rg_util_debug && |
|
1358 |
|
rg_log('DEBUG: No work to do anymore! Exit!'); |
|
1359 |
|
$ret['ok'] = 1; |
|
1360 |
|
break; |
|
1361 |
|
} |
|
1362 |
|
|
|
1363 |
|
if (empty($rx) && empty($wx)) { |
|
1364 |
|
$rg_util_debug && |
|
1365 |
|
rg_log('DEBUG: No events... sleeping'); |
|
1366 |
|
sleep(1); |
|
1367 |
|
continue; |
|
1368 |
|
} |
|
1369 |
|
|
|
1370 |
|
$revents = $rx; |
|
1371 |
|
$wevents = $wx; |
|
1372 |
|
$ex = NULL; |
|
1373 |
|
$rg_util_debug && rg_log('DEBUG: before stream_select:'); |
|
1374 |
|
$rg_util_debug && !empty($revents) && rg_log_ml('revents: ' . trim(print_r($revents, TRUE))); |
|
1375 |
|
$rg_util_debug && !empty($wevents) && rg_log_ml('wevents: ' . trim(print_r($wevents, TRUE))); |
|
1376 |
|
$r = stream_select($revents, $wevents, $ex, 1, 0); |
|
1377 |
|
if ($r === FALSE) { |
|
1378 |
|
$ret['errmsg'] = "cannot select"; |
|
1379 |
|
break; |
|
1380 |
|
} |
|
1381 |
|
|
|
1382 |
|
if (isset($a['cb_tick'])) |
|
1383 |
|
$a['cb_tick']($a); |
|
1384 |
|
|
|
1385 |
|
if ($r === 0) |
|
1386 |
|
continue; |
|
1387 |
|
|
|
1388 |
|
$rg_util_debug && rg_log('DEBUG: stream_select returned ' . $r . ' events.'); |
|
1389 |
|
$rg_util_debug && !empty($revents) && rg_log_ml('revents: ' . trim(print_r($revents, TRUE))); |
|
1390 |
|
$rg_util_debug && !empty($wevents) && rg_log_ml('wevents: ' . trim(print_r($wevents, TRUE))); |
|
1391 |
|
$rg_util_debug && !empty($ex) && rg_log_ml('ex: ' . trim(print_r($ex, TRUE))); |
|
1392 |
|
|
|
1393 |
|
foreach ($wevents as $fd) { |
|
1394 |
|
$ifd = intval($fd); |
|
1395 |
|
$index = $lut[$ifd]['index']; |
|
1396 |
|
$rg_util_debug && |
|
1397 |
|
rg_log('DEBUG: write event on ifd ' . $ifd |
|
1398 |
|
. ' index=' . $index . '!'); |
|
1399 |
|
|
|
1400 |
|
$info = &$a['cmds'][$index]; |
|
1401 |
|
|
|
1402 |
|
$rg_util_debug && |
|
1403 |
|
rg_log('DEBUG: out_buf before cb: ' . $info['out_buf']); |
|
1404 |
|
|
|
1405 |
|
// cb_output will populate $info['out_buf'] |
|
1406 |
|
if (isset($info['cb_output'])) |
|
1407 |
|
$info['cb_output']($index, $info); |
|
1408 |
|
|
|
1409 |
|
if (empty($info['out_buf'])) { |
|
1410 |
|
$rg_util_debug && |
|
1411 |
|
rg_log_ml('DEBUG: out_buf is empty!' . print_r($info, TRUE)); |
|
1412 |
|
continue; |
|
1413 |
|
} |
|
1414 |
|
|
|
1415 |
|
$rg_util_debug && |
|
1416 |
|
rg_log('DEBUG: SENDING: [' . $info['out_buf'] . ']'); |
|
1417 |
|
$r = @fwrite($fd, $info['out_buf']); |
|
1418 |
|
if ($r === FALSE) { |
|
1419 |
|
$info['last_errmsg'] = 'cannot write'; |
|
1420 |
|
if (isset($info['cb_error'])) |
|
1421 |
|
$info['cb_error']($index, $info, $info['last_errmsg']); |
|
1422 |
|
$info['needs_stop'] = TRUE; |
|
1423 |
|
continue; |
|
1424 |
|
} |
|
1425 |
|
$rg_util_debug && |
|
1426 |
|
rg_log('DEBUG: fwrite returned ' . $r . '.'); |
|
1427 |
|
$info['out_buf'] = substr($info['out_buf'], $r); |
|
1428 |
|
} |
|
1429 |
|
|
|
1430 |
|
foreach ($revents as $fd) { |
|
1431 |
|
$ifd = intval($fd); |
|
1432 |
|
$index = $lut[$ifd]['index']; |
|
1433 |
|
$stream = $lut[$ifd]['stream']; |
|
1434 |
|
$rg_util_debug && |
|
1435 |
|
rg_log('DEBUG: read event on ifd ' . $ifd |
|
1436 |
|
. ' index=' . $index . ', stream=' . $stream . '!'); |
|
1437 |
|
|
|
1438 |
|
$info = &$a['cmds'][$index]; |
|
1439 |
|
|
|
1440 |
|
$_d = @fread($fd, 32 * 4096); |
|
1441 |
|
if ($_d === FALSE) { |
|
1442 |
|
$rg_util_debug && |
|
1443 |
|
rg_log('DEBUG: ifd ' . $ifd . ' fread returned FALSE'); |
|
1444 |
|
$info['last_errmsg'] = 'cannot read'; |
|
1445 |
|
if (isset($info['cb_error'])) |
|
1446 |
|
$info['cb_error']($index, $info, $info['last_errmsg']); |
|
1447 |
|
$info['needs_stop'] = TRUE; |
|
1448 |
|
continue; |
|
1449 |
|
} |
|
1450 |
|
|
|
1451 |
|
if (empty($_d)) { |
|
1452 |
|
$rg_util_debug && |
|
1453 |
|
rg_log('DEBUG: ifd ' . $ifd . ' returned no data.'); |
|
1454 |
|
$info['closed'][$stream] = 1; |
|
1455 |
|
continue; |
|
1456 |
|
} |
|
1457 |
|
|
|
1458 |
|
$info['last_activity'] = time(); |
|
1459 |
|
$rg_util_debug && |
|
1460 |
|
rg_log('DEBUG: index ' . $index . ': set last_activity to ' . $info['last_activity']); |
|
1461 |
|
|
|
1462 |
|
switch ($stream) { |
|
1463 |
|
case 1: $info['in_buf'] .= $_d; break; |
|
1464 |
|
case 2: $info['err_buf'] .= $_d; break; |
|
1465 |
|
} |
|
1466 |
|
|
|
1467 |
|
if (isset($info['cb_input'])) |
|
1468 |
|
$info['cb_input']($index, $info, $stream); |
|
1469 |
|
} |
|
1470 |
|
} |
|
1471 |
|
|
|
1472 |
|
rg_log_exit(); |
|
1473 |
|
rg_prof_end('exec2'); |
|
1474 |
|
return $ret; |
|
1475 |
|
} |
|
1476 |
|
|
1192 |
1477 |
/* |
/* |
1193 |
1478 |
* Force browser to redirect to another page |
* Force browser to redirect to another page |
1194 |
1479 |
*/ |
*/ |
|
... |
... |
$rg_socket_cache = array(); |
1530 |
1815 |
*/ |
*/ |
1531 |
1816 |
function rg_socket_recv_wait($socket, $wait, $timeout) |
function rg_socket_recv_wait($socket, $wait, $timeout) |
1532 |
1817 |
{ |
{ |
1533 |
|
rg_prof_start('sock_recv_wait'); |
|
1534 |
|
|
|
1535 |
|
$ret = FALSE; |
|
|
1818 |
|
rg_prof_start('socket_recv_wait'); |
1536 |
1819 |
|
|
1537 |
1820 |
if ($timeout === NULL) { |
if ($timeout === NULL) { |
1538 |
1821 |
$tv_sec = NULL; |
$tv_sec = NULL; |
|
... |
... |
function rg_socket_recv_wait($socket, $wait, $timeout) |
1543 |
1826 |
} |
} |
1544 |
1827 |
|
|
1545 |
1828 |
$ret_buf = ''; |
$ret_buf = ''; |
|
1829 |
|
$ret = FALSE; |
1546 |
1830 |
while (1) { |
while (1) { |
1547 |
1831 |
$reads = array($socket); $writes = array(); $ex = array(); |
$reads = array($socket); $writes = array(); $ex = array(); |
1548 |
1832 |
$r = @socket_select($reads, $writes, $ex, $tv_sec, $tv_usec); |
$r = @socket_select($reads, $writes, $ex, $tv_sec, $tv_usec); |
|
... |
... |
function rg_socket_recv_wait($socket, $wait, $timeout) |
1552 |
1836 |
} |
} |
1553 |
1837 |
|
|
1554 |
1838 |
if ($r === 0) { // timeout |
if ($r === 0) { // timeout |
1555 |
|
rg_log('Timeout in reading!'); |
|
|
1839 |
|
rg_log('Timeout reading from socket!'); |
1556 |
1840 |
break; |
break; |
1557 |
1841 |
} |
} |
1558 |
1842 |
|
|
|
... |
... |
function rg_socket_recv_wait($socket, $wait, $timeout) |
1578 |
1862 |
break; |
break; |
1579 |
1863 |
} |
} |
1580 |
1864 |
|
|
1581 |
|
rg_prof_end('sock_recv_wait'); |
|
|
1865 |
|
rg_prof_end('socket_recv_wait'); |
1582 |
1866 |
return $ret; |
return $ret; |
1583 |
1867 |
} |
} |
1584 |
1868 |
|
|
|
... |
... |
function rg_echo($s) |
1836 |
2120 |
echo $s; |
echo $s; |
1837 |
2121 |
} |
} |
1838 |
2122 |
|
|
|
2123 |
|
/* |
|
2124 |
|
* Function used to register login functions |
|
2125 |
|
*/ |
|
2126 |
|
$rg_login_functions = array(); |
|
2127 |
|
function rg_register_login_function($f) |
|
2128 |
|
{ |
|
2129 |
|
global $rg_login_functions; |
|
2130 |
|
|
|
2131 |
|
$rg_login_functions[] = $f; |
|
2132 |
|
} |
|
2133 |
|
|
1839 |
2134 |
?> |
?> |
File tests/ldap.php added (mode: 100644) (index 0000000..c306001) |
|
1 |
|
<?php |
|
2 |
|
error_reporting(E_ALL | E_STRICT); |
|
3 |
|
ini_set('track_errors', 'On'); |
|
4 |
|
|
|
5 |
|
$rg_cache_debug = TRUE; |
|
6 |
|
$rg_util_debug = TRUE; |
|
7 |
|
$rg_sql_debug = 100; |
|
8 |
|
|
|
9 |
|
$INC = dirname(__FILE__) . '/../inc'; |
|
10 |
|
require_once(dirname(__FILE__) . '/config.php'); |
|
11 |
|
require_once($INC . '/init.inc.php'); |
|
12 |
|
require_once($INC . '/util.inc.php'); |
|
13 |
|
require_once($INC . '/ldap.inc.php'); |
|
14 |
|
require_once($INC . '/ldap_sync.inc.php'); |
|
15 |
|
require_once('helpers.inc.php'); |
|
16 |
|
require_once('http.inc.php'); |
|
17 |
|
|
|
18 |
|
rg_log_set_file('ldap.log'); |
|
19 |
|
|
|
20 |
|
$rg_sql = 'host=localhost user=rocketgit dbname=rocketgit connect_timeout=10'; |
|
21 |
|
$rg_no_db = TRUE; |
|
22 |
|
require_once('common.php'); |
|
23 |
|
|
|
24 |
|
$_testns = 'admin_ldap'; |
|
25 |
|
$rg_cache_enable = TRUE; |
|
26 |
|
$rg_cache_debug = TRUE; |
|
27 |
|
|
|
28 |
|
|
|
29 |
|
function rg_ldap_start_server(&$l) |
|
30 |
|
{ |
|
31 |
|
$prep = 'ldap/chroot-' . $l['rg_ldap_ns'] . '/prep.done'; |
|
32 |
|
$r = @unlink($prep); |
|
33 |
|
rg_log('unlinking prep.done returned ' . ($r === FALSE ? 'false' : 'true')); |
|
34 |
|
|
|
35 |
|
$log = __DIR__ . '/ldap-' . $l['rg_ldap_port'] . '.log'; |
|
36 |
|
|
|
37 |
|
$pid = pcntl_fork(); |
|
38 |
|
if ($pid == 0) { // child |
|
39 |
|
foreach ($l as $k => $v) { |
|
40 |
|
rg_log($k . '=' . $v); |
|
41 |
|
putenv($k . '=' . $v); |
|
42 |
|
} |
|
43 |
|
rg_exec('cd ldap && sh start.sh &> ' . $log, '', FALSE, FALSE); |
|
44 |
|
|
|
45 |
|
$log = '../ldap-' . $l['rg_ldap_port'] . 'prep.log'; |
|
46 |
|
rg_exec('cd ldap && sh prepare.sh &> ' . $log, '', FALSE, FALSE); |
|
47 |
|
exit(0); |
|
48 |
|
} |
|
49 |
|
|
|
50 |
|
rg_log('Child started with pid ' . $pid); |
|
51 |
|
|
|
52 |
|
rg_log('Waiting for preparation to finish...'); |
|
53 |
|
$tries = 200; |
|
54 |
|
while ($tries-- > 0) { |
|
55 |
|
$x = @file_get_contents($prep); |
|
56 |
|
if ($x !== FALSE) |
|
57 |
|
break; |
|
58 |
|
|
|
59 |
|
rg_log('prep file [' . $prep . '] is not present, wait.'); |
|
60 |
|
usleep(100000); |
|
61 |
|
} |
|
62 |
|
|
|
63 |
|
if ($tries == 0) { |
|
64 |
|
rg_log('Could not prepare! Exit!'); |
|
65 |
|
posix_kill($pid, SIGKILL); |
|
66 |
|
exit(1); |
|
67 |
|
} |
|
68 |
|
|
|
69 |
|
$l['log'] = $log; |
|
70 |
|
} |
|
71 |
|
|
|
72 |
|
function clean($log) |
|
73 |
|
{ |
|
74 |
|
rg_log('Cleaning processes attached to file ' . $log . '...'); |
|
75 |
|
$r = rg_exec('fuser -k -v -9 ' . escapeshellarg($log), '', FALSE, FALSE); |
|
76 |
|
rg_log_ml('fuser returned: ' . print_r($r, TRUE)); |
|
77 |
|
} |
|
78 |
|
|
|
79 |
|
|
|
80 |
|
prepare_http(); |
|
81 |
|
|
|
82 |
|
$rg_ui = array('is_admin' => 1); |
|
83 |
|
rg_test_create_user($db, $rg_ui); |
|
84 |
|
$r = test_login($test_url, $rg_ui); |
|
85 |
|
if ($r === FALSE) { |
|
86 |
|
rg_log("Cannot login!"); |
|
87 |
|
exit(1); |
|
88 |
|
} |
|
89 |
|
|
|
90 |
|
|
|
91 |
|
rg_log(''); |
|
92 |
|
rg_log('Generating certificates...'); |
|
93 |
|
$r = rg_exec('./ca.sh ldap', '', FALSE, FALSE); |
|
94 |
|
if (!strstr($r['data'], 'CA_SH_OK')) { |
|
95 |
|
rg_log_ml('data: ' . $r['data']); |
|
96 |
|
rg_log('Cannot generate certificates!'); |
|
97 |
|
exit(1); |
|
98 |
|
} |
|
99 |
|
|
|
100 |
|
|
|
101 |
|
$bind_addr = '127.' . rand(1, 255) . '.' . rand(1,255) . '.' . rand(2,255); |
|
102 |
|
$bind_port = 65100; $bind_ports = 65101; |
|
103 |
|
$pass = rg_id(16); |
|
104 |
|
$user_pass = rg_id(16); |
|
105 |
|
$user_key = rg_id(16); |
|
106 |
|
rg_log('bind_addr=' . $bind_addr . ' bind_port=' . $bind_port |
|
107 |
|
. ' bind_ports=' . $bind_ports . ' pass=' . $pass |
|
108 |
|
. ' user_pass=' . $user_pass . ' user_key=' . $user_key); |
|
109 |
|
|
|
110 |
|
|
|
111 |
|
rg_log(''); |
|
112 |
|
rg_log_enter('Deleting all LDAP servers'); |
|
113 |
|
$sql = 'TRUNCATE ldap_servers'; |
|
114 |
|
$res = rg_sql_query($db, $sql); |
|
115 |
|
if ($res === FALSE) { |
|
116 |
|
rg_log('Cannot delete all LDAP servers'); |
|
117 |
|
exit(1); |
|
118 |
|
} |
|
119 |
|
rg_sql_free_result($res); |
|
120 |
|
rg_cache_unset('ldap', RG_SOCKET_NO_WAIT); |
|
121 |
|
rg_log_exit(); |
|
122 |
|
|
|
123 |
|
|
|
124 |
|
rg_log(''); |
|
125 |
|
rg_log_enter('Deleting LDAP cache'); |
|
126 |
|
$sql = 'TRUNCATE ldap_cache'; |
|
127 |
|
$res = rg_sql_query($db, $sql); |
|
128 |
|
if ($res === FALSE) { |
|
129 |
|
rg_log('Cannot delete LDAP cache'); |
|
130 |
|
exit(1); |
|
131 |
|
} |
|
132 |
|
rg_sql_free_result($res); |
|
133 |
|
//TODO rg_cache_unset('ldap_cache', RG_SOCKET_NO_WAIT); |
|
134 |
|
rg_log_exit(); |
|
135 |
|
|
|
136 |
|
|
|
137 |
|
rg_log(''); |
|
138 |
|
rg_log_enter('Loading Admin -> LDAP -> Add...'); |
|
139 |
|
$data = array(); |
|
140 |
|
$headers = array(); |
|
141 |
|
$r = do_req($test_url . '/op/admin/ldap/add', $data, $headers); |
|
142 |
|
if ($r === FALSE) { |
|
143 |
|
rg_log('Cannot load add page!'); |
|
144 |
|
exit(1); |
|
145 |
|
} |
|
146 |
|
if (!isset($r['tokens']['ldap_add'])) { |
|
147 |
|
rg_log_ml('r:' . print_r($r, TRUE)); |
|
148 |
|
rg_log('No ldap_add token?!'); |
|
149 |
|
exit(1); |
|
150 |
|
} |
|
151 |
|
$token = $r['tokens']['ldap_add']; |
|
152 |
|
$id = rg_id(8); |
|
153 |
|
$name = 'server-' . $id . ' <xss>'; |
|
154 |
|
|
|
155 |
|
rg_log('Posting the form...'); |
|
156 |
|
$data = array( |
|
157 |
|
'doit' => 1, |
|
158 |
|
'token' => $token, |
|
159 |
|
'ldap::id' => 0, |
|
160 |
|
'ldap::plan_id' => 0, |
|
161 |
|
'ldap::prio' => 10, |
|
162 |
|
'ldap::session_time' => 600, |
|
163 |
|
'ldap::name' => $name, |
|
164 |
|
'ldap::url' => 'ldap://' . $bind_addr . ':' . $bind_port, |
|
165 |
|
'ldap::bind_dn' => '', |
|
166 |
|
'ldap::bind_pass' => '', |
|
167 |
|
'ldap::user_base' => 'dc=my-domain,dc=com', |
|
168 |
|
'ldap::uid_attr' => 'uid', |
|
169 |
|
'ldap::filter' => 'memberOf=cn=group1,ou=Group,dc=my-domain,dc=com', |
|
170 |
|
'ldap::group_base' => 'dc=my-domain,dc=com', |
|
171 |
|
'ldap::group_attr' => 'memberOf', |
|
172 |
|
'ldap::group_filter' => '', |
|
173 |
|
'ldap::admin_group' => 'cn=(Admins|Admins2),ou=Group,dc=my-domain,dc=com', |
|
174 |
|
'ldap::ca_cert' => '' |
|
175 |
|
); |
|
176 |
|
$r = do_req($test_url . '/op/admin/ldap/add', $data, $headers); |
|
177 |
|
if (!strstr($r['body'], 'Configuration has been successfully saved.')) { |
|
178 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
179 |
|
rg_log('Cannot post form (expected answer missing)!'); |
|
180 |
|
exit(1); |
|
181 |
|
} |
|
182 |
|
rg_log_exit(); |
|
183 |
|
|
|
184 |
|
|
|
185 |
|
rg_log(''); |
|
186 |
|
rg_log_enter('Loading Admin -> LDAP -> List...'); |
|
187 |
|
$data = array(); |
|
188 |
|
$headers = array(); |
|
189 |
|
$r = do_req($test_url . '/op/admin/ldap/list', $data, $headers); |
|
190 |
|
if ($r === FALSE) { |
|
191 |
|
rg_log('Cannot load list page!'); |
|
192 |
|
exit(1); |
|
193 |
|
} |
|
194 |
|
// TODO, here test that everything is present in the list |
|
195 |
|
$token = $r['tokens']['ldap_list']; |
|
196 |
|
rg_log_exit(); |
|
197 |
|
|
|
198 |
|
|
|
199 |
|
rg_log(''); |
|
200 |
|
rg_log_enter('Setting up two LDAP servers in mirror mode...'); |
|
201 |
|
// We are forced to close the connection, else will get a nasty error, |
|
202 |
|
// Even if the child is not doing anything with the connection. |
|
203 |
|
rg_sql_close($db); |
|
204 |
|
$l1 = array( |
|
205 |
|
'rg_ldap_ns' => 's1', |
|
206 |
|
'rg_ldap_addr' => $bind_addr, |
|
207 |
|
'rg_ldap_port' => $bind_port, |
|
208 |
|
'rg_ldap_ports' => $bind_ports, |
|
209 |
|
'rg_ldap_server_id' => '001', |
|
210 |
|
'rg_ldap_producer_url' => 'ldap://' . $bind_addr . ':' . ($bind_port + 2), |
|
211 |
|
'rg_ldap_producer_rid' => '002', |
|
212 |
|
'rg_ldap_add_data' => 1, |
|
213 |
|
'rg_ldap_pass' => $pass, |
|
214 |
|
'rg_ldap_user_pass' => $user_pass, |
|
215 |
|
'rg_ldap_user_key' => $user_key |
|
216 |
|
); |
|
217 |
|
rg_ldap_start_server($l1); |
|
218 |
|
|
|
219 |
|
$l2 = array( |
|
220 |
|
'rg_ldap_ns' => 's2', |
|
221 |
|
'rg_ldap_addr' => $bind_addr, |
|
222 |
|
'rg_ldap_port' => $bind_port + 2, |
|
223 |
|
'rg_ldap_ports' => $bind_ports + 2, |
|
224 |
|
'rg_ldap_server_id' => '002', |
|
225 |
|
'rg_ldap_producer_url' => 'ldap://' . $bind_addr . ':' . $bind_port, |
|
226 |
|
'rg_ldap_producer_rid' => '001', |
|
227 |
|
'rg_ldap_add_data' => 0, |
|
228 |
|
'rg_ldap_pass' => $pass, |
|
229 |
|
'rg_ldap_user_pass' => $user_pass, |
|
230 |
|
'rg_ldap_user_key' => $user_key |
|
231 |
|
); |
|
232 |
|
rg_ldap_start_server($l2); |
|
233 |
|
|
|
234 |
|
register_shutdown_function('clean', $l1['log']); |
|
235 |
|
register_shutdown_function('clean', $l2['log']); |
|
236 |
|
|
|
237 |
|
$data = array( |
|
238 |
|
'addr' => $bind_addr, |
|
239 |
|
'port' => $bind_port, |
|
240 |
|
'bind_user' => 'cn=Manager,dc=my-domain,dc=com', |
|
241 |
|
'bind_pass' => $pass, |
|
242 |
|
'base' => 'dc=my-domain,dc=com' |
|
243 |
|
); |
|
244 |
|
rg_log_exit(); |
|
245 |
|
|
|
246 |
|
|
|
247 |
|
rg_log(''); |
|
248 |
|
rg_log_enter('Find out the id of the server...'); |
|
249 |
|
$r = rg_ldap_list($db); |
|
250 |
|
if ($r['ok'] !== 1) { |
|
251 |
|
rg_log('Cannot get the ldap servers list: ' . $r['errmsg']); |
|
252 |
|
exit(1); |
|
253 |
|
} |
|
254 |
|
$found = FALSE; |
|
255 |
|
foreach ($r['list'] as $id => $info) { |
|
256 |
|
if (strcmp($info['url'], 'ldap://' . $bind_addr . ':' . $bind_port) != 0) |
|
257 |
|
continue; |
|
258 |
|
|
|
259 |
|
$found = TRUE; |
|
260 |
|
break; |
|
261 |
|
} |
|
262 |
|
if (!$found) { |
|
263 |
|
rg_log('Could not find the server in database!'); |
|
264 |
|
exit(1); |
|
265 |
|
} |
|
266 |
|
$data['server_id'] = $id; |
|
267 |
|
rg_log_exit(); |
|
268 |
|
|
|
269 |
|
|
|
270 |
|
/* TODO: this has to be made available after I deal with the sync |
|
271 |
|
rg_log(''); |
|
272 |
|
rg_log_enter('sync_ro...'); |
|
273 |
|
$r = rg_ldap_sync_ro($db, $data); |
|
274 |
|
if ($r['ok'] != 1) { |
|
275 |
|
rg_log('Cannot sync: ' . $r['errmsg'] . '!'); |
|
276 |
|
exit(1); |
|
277 |
|
} |
|
278 |
|
rg_log_exit(); |
|
279 |
|
|
|
280 |
|
|
|
281 |
|
rg_log(''); |
|
282 |
|
rg_log_enter('Deleting user user4...'); |
|
283 |
|
$r = rg_ldap_core_connect('ldap://' . $l1['rg_ldap_addr'] |
|
284 |
|
. ':' . $l1['rg_ldap_port']); |
|
285 |
|
if ($r['ok'] !== 1) { |
|
286 |
|
rg_log('Cannot connect to second server: ' . $r['errmsg'] . '!'); |
|
287 |
|
exit(1); |
|
288 |
|
} |
|
289 |
|
$con = $r['con']; |
|
290 |
|
$r = rg_ldap_core_bind($con, 'cn=Manager,dc=my-domain,dc=com', $pass); |
|
291 |
|
if ($r['ok'] !== 1) { |
|
292 |
|
rg_log('cannot bind: ' . $r['errmsg']); |
|
293 |
|
exit(1); |
|
294 |
|
} |
|
295 |
|
$r = rg_ldap_core_del($con, 'uid=user4,ou=People,dc=my-domain,dc=com'); |
|
296 |
|
if ($r['ok'] !== 1) { |
|
297 |
|
rg_log('Cannot delete: ' . $r['errmsg'] . '!'); |
|
298 |
|
exit(1); |
|
299 |
|
} |
|
300 |
|
rg_log_exit(); |
|
301 |
|
|
|
302 |
|
// TODO: needed?! |
|
303 |
|
sleep(3); |
|
304 |
|
|
|
305 |
|
|
|
306 |
|
rg_log(''); |
|
307 |
|
rg_log_enter('get server CSN field...'); |
|
308 |
|
$res = rg_sql_query($db, 'SELECT csn FROM ldap_servers' |
|
309 |
|
. ' WHERE id = ' . $data['server_id']); |
|
310 |
|
if ($res === FALSE) { |
|
311 |
|
rg_log('Cannot select csn from db: ' . rg_sql_error() . '!'); |
|
312 |
|
exit(1); |
|
313 |
|
} |
|
314 |
|
$row = rg_sql_fetch_array($res); |
|
315 |
|
rg_sql_free_result($res); |
|
316 |
|
$csn = $row['csn']; |
|
317 |
|
rg_log('csn: ' . $csn); |
|
318 |
|
rg_log_exit(); |
|
319 |
|
|
|
320 |
|
|
|
321 |
|
rg_log(''); |
|
322 |
|
rg_log_enter('sync_ro (after a delete)...'); |
|
323 |
|
$data['rid'] = '001'; $data['csn'] = $csn; // not sure if rid is correct TODO |
|
324 |
|
$r = rg_ldap_sync_ro($db, $data); |
|
325 |
|
if ($r['ok'] != 1) { |
|
326 |
|
rg_log('Cannot sync: ' . $r['errmsg'] . '!'); |
|
327 |
|
exit(1); |
|
328 |
|
} |
|
329 |
|
rg_log_exit(); |
|
330 |
|
*/ |
|
331 |
|
|
|
332 |
|
|
|
333 |
|
rg_log(''); |
|
334 |
|
rg_log_enter('Login using a LDAP user using ldap uid (first login)'); |
|
335 |
|
$_ui = array( |
|
336 |
|
'username' => 'user1-' . $user_key, |
|
337 |
|
'pass' => $user_pass, |
|
338 |
|
't' => 'first login by uid' |
|
339 |
|
); |
|
340 |
|
$r = test_login($test_url, $_ui); |
|
341 |
|
if ($r === FALSE) |
|
342 |
|
exit(1); |
|
343 |
|
rg_log_exit(); |
|
344 |
|
|
|
345 |
|
|
|
346 |
|
rg_log(''); |
|
347 |
|
rg_log_enter('Setting ldap_cache.uid to 0 to trigger a conflict in inserting' |
|
348 |
|
. ' in \'users\' table'); |
|
349 |
|
$params = array('user' => 'user1-' . $user_key); |
|
350 |
|
$sql = 'UPDATE ldap_cache SET uid = 0 WHERE ldap_uid = @@user@@'; |
|
351 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
352 |
|
if ($res === FALSE) { |
|
353 |
|
rg_log('Cannot update ldap_cache.uid!'); |
|
354 |
|
exit(1); |
|
355 |
|
} |
|
356 |
|
rg_sql_free_result($res); |
|
357 |
|
rg_log_exit(); |
|
358 |
|
|
|
359 |
|
|
|
360 |
|
rg_log(''); |
|
361 |
|
// User will not be found in 'users' table because we search by e-mail |
|
362 |
|
rg_log_enter('Login using a LDAP user: mail'); |
|
363 |
|
$_ui = array( |
|
364 |
|
'username' => 'user1-' . $user_key . '@my-domain.com', |
|
365 |
|
'pass' => $user_pass, |
|
366 |
|
't' => 'login by e-mail expecting conflict inserting into users table' |
|
367 |
|
); |
|
368 |
|
$r = test_login($test_url, $_ui); |
|
369 |
|
if ($r === FALSE) |
|
370 |
|
exit(1); |
|
371 |
|
rg_log_exit(); |
|
372 |
|
|
|
373 |
|
|
|
374 |
|
rg_log(''); |
|
375 |
|
rg_log_enter('Login using a LDAP user: uid (second time, expect user present)'); |
|
376 |
|
$_ui = array( |
|
377 |
|
'username' => 'user1-' . $user_key, |
|
378 |
|
'pass' => $user_pass, |
|
379 |
|
't' => 'second login by uid, expecting user present in users table' |
|
380 |
|
); |
|
381 |
|
$r = test_login($test_url, $_ui); |
|
382 |
|
if ($r === FALSE) { |
|
383 |
|
rg_log('Cannot login!'); |
|
384 |
|
exit(1); |
|
385 |
|
} |
|
386 |
|
rg_log_exit(); |
|
387 |
|
|
|
388 |
|
|
|
389 |
|
rg_log(''); |
|
390 |
|
rg_log_enter('Login using a LDAP user: uid (third time, but delete from' |
|
391 |
|
. ' \'users\' table first)'); |
|
392 |
|
$params = array( |
|
393 |
|
'new' => 'user1-fake-' . $user_key, |
|
394 |
|
'old' => 'user1-' . $user_key |
|
395 |
|
); |
|
396 |
|
// First, find out the uid |
|
397 |
|
$sql = 'SELECT uid FROM users WHERE username = @@old@@'; |
|
398 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
399 |
|
if ($res === FALSE) { |
|
400 |
|
rg_log('Cannot get info user1 username!'); |
|
401 |
|
exit(1); |
|
402 |
|
} |
|
403 |
|
$row = rg_sql_fetch_array($res); |
|
404 |
|
rg_sql_free_result($res); |
|
405 |
|
$params['uid'] = $row['uid']; |
|
406 |
|
|
|
407 |
|
$sql = 'UPDATE users SET username = @@new@@ WHERE uid = @@uid@@'; |
|
408 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
409 |
|
if ($res === FALSE) { |
|
410 |
|
rg_log('Cannot update user1 username!'); |
|
411 |
|
exit(1); |
|
412 |
|
} |
|
413 |
|
|
|
414 |
|
$k = 'username_to_uid::user1-' . $user_key; |
|
415 |
|
rg_cache_unset($k, RG_SOCKET_NO_WAIT); |
|
416 |
|
|
|
417 |
|
$k = 'user::' . $params['uid']; |
|
418 |
|
rg_cache_unset($k, RG_SOCKET_NO_WAIT); |
|
419 |
|
|
|
420 |
|
$_ui = array( |
|
421 |
|
'username' => 'user1-' . $user_key, |
|
422 |
|
'pass' => $user_pass, |
|
423 |
|
't' => 'login by uid, but delete from users before' |
|
424 |
|
); |
|
425 |
|
$r = test_login($test_url, $_ui); |
|
426 |
|
if ($r === FALSE) { |
|
427 |
|
rg_log('Cannot login!'); |
|
428 |
|
exit(1); |
|
429 |
|
} |
|
430 |
|
rg_log_exit(); |
|
431 |
|
|
|
432 |
|
|
|
433 |
|
rg_log(''); |
|
434 |
|
rg_log_enter('We try to login with user2, which have the description as the uid'); |
|
435 |
|
rg_log('Updating LDAP server...'); |
|
436 |
|
rg_cache_set('ldap::list::' . $data['server_id'] . '::uid_attr', |
|
437 |
|
'DescriptioN', RG_SOCKET_NO_WAIT); |
|
438 |
|
$_ui = array( |
|
439 |
|
'username' => 'user2-' . $user_key, |
|
440 |
|
'pass' => $user_pass, |
|
441 |
|
't' => 'now, the uid attr field is description' |
|
442 |
|
); |
|
443 |
|
$r = test_login($test_url, $_ui); |
|
444 |
|
if ($r === FALSE) { |
|
445 |
|
rg_log('Cannot login!'); |
|
446 |
|
exit(1); |
|
447 |
|
} |
|
448 |
|
rg_log_exit(); |
|
449 |
|
|
|
450 |
|
|
|
451 |
|
rg_log(''); |
|
452 |
|
rg_log_enter('Login again as the admin user...'); |
|
453 |
|
$r = test_login($test_url, $rg_ui); |
|
454 |
|
if ($r === FALSE) { |
|
455 |
|
rg_log("Cannot login!"); |
|
456 |
|
exit(1); |
|
457 |
|
} |
|
458 |
|
rg_log_exit(); |
|
459 |
|
|
|
460 |
|
|
|
461 |
|
rg_log(''); |
|
462 |
|
rg_log_enter('Loading Admin -> LDAP -> List (for delete)...'); |
|
463 |
|
$data = array(); |
|
464 |
|
$headers = array(); |
|
465 |
|
$r = do_req($test_url . '/op/admin/ldap/list', $data, $headers); |
|
466 |
|
if ($r === FALSE) { |
|
467 |
|
rg_log('Cannot load list page!'); |
|
468 |
|
exit(1); |
|
469 |
|
} |
|
470 |
|
$token = $r['tokens']['ldap_list']; |
|
471 |
|
rg_log_exit(); |
|
472 |
|
|
|
473 |
|
|
|
474 |
|
rg_log(''); |
|
475 |
|
rg_log_enter('Deleting a LDAP server...'); |
|
476 |
|
$sql = 'SELECT id FROM ldap_servers WHERE name = @@name@@ AND who = @@who@@'; |
|
477 |
|
$params = array('who' => $rg_ui['uid'], 'name' => $name); |
|
478 |
|
$res = rg_sql_query_params($db, $sql, $params); |
|
479 |
|
if ($res === FALSE) { |
|
480 |
|
rg_log('Cannot do the select query: ' . rg_sql_error() . '!'); |
|
481 |
|
exit(1); |
|
482 |
|
} |
|
483 |
|
$row = rg_sql_fetch_array($res); |
|
484 |
|
rg_sql_free_result($res); |
|
485 |
|
$_id = $row['id']; |
|
486 |
|
$data = array( |
|
487 |
|
'delete' => 1, |
|
488 |
|
'token' => $token, |
|
489 |
|
'delete_list[' . $_id . ']' => 'on' |
|
490 |
|
); |
|
491 |
|
$headers = array(); |
|
492 |
|
$r = do_req($test_url . '/op/admin/ldap/list', $data, $headers); |
|
493 |
|
if ($r === FALSE) { |
|
494 |
|
rg_log('Cannot load list page!'); |
|
495 |
|
exit(1); |
|
496 |
|
} |
|
497 |
|
if (!strstr($r['body'], 'The selected LDAP servers have been successfully deleted.')) { |
|
498 |
|
rg_log_ml('r: ' . print_r($r, TRUE)); |
|
499 |
|
rg_log('Cannot delete LDAP server!'); |
|
500 |
|
exit(1); |
|
501 |
|
} |
|
502 |
|
rg_log_exit(); |
|
503 |
|
|
|
504 |
|
|
|
505 |
|
rg_log('OK!'); |
|
506 |
|
?> |
File tests/ldap/conf.tmpl/cn=config/cn=schema/cn={0}core.ldif added (mode: 100644) (index 0000000..9752c08) |
|
1 |
|
# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. |
|
2 |
|
# CRC32 8757baa8 |
|
3 |
|
dn: cn={0}core |
|
4 |
|
objectClass: olcSchemaConfig |
|
5 |
|
cn: {0}core |
|
6 |
|
olcAttributeTypes: {0}( 2.5.4.2 NAME 'knowledgeInformation' DESC 'RFC2256: k |
|
7 |
|
nowledge information' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115. |
|
8 |
|
121.1.15{32768} ) |
|
9 |
|
olcAttributeTypes: {1}( 2.5.4.4 NAME ( 'sn' 'surname' ) DESC 'RFC2256: last |
|
10 |
|
(family) name(s) for which the entity is known by' SUP name ) |
|
11 |
|
olcAttributeTypes: {2}( 2.5.4.5 NAME 'serialNumber' DESC 'RFC2256: serial nu |
|
12 |
|
mber of the entity' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMat |
|
13 |
|
ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} ) |
|
14 |
|
olcAttributeTypes: {3}( 2.5.4.6 NAME ( 'c' 'countryName' ) DESC 'RFC4519: tw |
|
15 |
|
o-letter ISO-3166 country code' SUP name SYNTAX 1.3.6.1.4.1.1466.115.121.1. |
|
16 |
|
11 SINGLE-VALUE ) |
|
17 |
|
olcAttributeTypes: {4}( 2.5.4.7 NAME ( 'l' 'localityName' ) DESC 'RFC2256: l |
|
18 |
|
ocality which this object resides in' SUP name ) |
|
19 |
|
olcAttributeTypes: {5}( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' ) DESC 'RF |
|
20 |
|
C2256: state or province which this object resides in' SUP name ) |
|
21 |
|
olcAttributeTypes: {6}( 2.5.4.9 NAME ( 'street' 'streetAddress' ) DESC 'RFC2 |
|
22 |
|
256: street address of this object' EQUALITY caseIgnoreMatch SUBSTR caseIgn |
|
23 |
|
oreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) |
|
24 |
|
olcAttributeTypes: {7}( 2.5.4.10 NAME ( 'o' 'organizationName' ) DESC 'RFC22 |
|
25 |
|
56: organization this object belongs to' SUP name ) |
|
26 |
|
olcAttributeTypes: {8}( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' ) DESC |
|
27 |
|
'RFC2256: organizational unit this object belongs to' SUP name ) |
|
28 |
|
olcAttributeTypes: {9}( 2.5.4.12 NAME 'title' DESC 'RFC2256: title associate |
|
29 |
|
d with the entity' SUP name ) |
|
30 |
|
olcAttributeTypes: {10}( 2.5.4.14 NAME 'searchGuide' DESC 'RFC2256: search g |
|
31 |
|
uide, deprecated by enhancedSearchGuide' SYNTAX 1.3.6.1.4.1.1466.115.121.1. |
|
32 |
|
25 ) |
|
33 |
|
olcAttributeTypes: {11}( 2.5.4.15 NAME 'businessCategory' DESC 'RFC2256: bus |
|
34 |
|
iness category' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch S |
|
35 |
|
YNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) |
|
36 |
|
olcAttributeTypes: {12}( 2.5.4.16 NAME 'postalAddress' DESC 'RFC2256: postal |
|
37 |
|
address' EQUALITY caseIgnoreListMatch SUBSTR caseIgnoreListSubstringsMatch |
|
38 |
|
SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 ) |
|
39 |
|
olcAttributeTypes: {13}( 2.5.4.17 NAME 'postalCode' DESC 'RFC2256: postal co |
|
40 |
|
de' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6. |
|
41 |
|
1.4.1.1466.115.121.1.15{40} ) |
|
42 |
|
olcAttributeTypes: {14}( 2.5.4.18 NAME 'postOfficeBox' DESC 'RFC2256: Post O |
|
43 |
|
ffice Box' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX |
|
44 |
|
1.3.6.1.4.1.1466.115.121.1.15{40} ) |
|
45 |
|
olcAttributeTypes: {15}( 2.5.4.19 NAME 'physicalDeliveryOfficeName' DESC 'RF |
|
46 |
|
C2256: Physical Delivery Office Name' EQUALITY caseIgnoreMatch SUBSTR caseI |
|
47 |
|
gnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} ) |
|
48 |
|
olcAttributeTypes: {16}( 2.5.4.20 NAME 'telephoneNumber' DESC 'RFC2256: Tele |
|
49 |
|
phone Number' EQUALITY telephoneNumberMatch SUBSTR telephoneNumberSubstring |
|
50 |
|
sMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} ) |
|
51 |
|
olcAttributeTypes: {17}( 2.5.4.21 NAME 'telexNumber' DESC 'RFC2256: Telex Nu |
|
52 |
|
mber' SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 ) |
|
53 |
|
olcAttributeTypes: {18}( 2.5.4.22 NAME 'teletexTerminalIdentifier' DESC 'RFC |
|
54 |
|
2256: Teletex Terminal Identifier' SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 ) |
|
55 |
|
olcAttributeTypes: {19}( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' ) |
|
56 |
|
DESC 'RFC2256: Facsimile (Fax) Telephone Number' SYNTAX 1.3.6.1.4.1.1466.11 |
|
57 |
|
5.121.1.22 ) |
|
58 |
|
olcAttributeTypes: {20}( 2.5.4.24 NAME 'x121Address' DESC 'RFC2256: X.121 Ad |
|
59 |
|
dress' EQUALITY numericStringMatch SUBSTR numericStringSubstringsMatch SYNT |
|
60 |
|
AX 1.3.6.1.4.1.1466.115.121.1.36{15} ) |
|
61 |
|
olcAttributeTypes: {21}( 2.5.4.25 NAME 'internationaliSDNNumber' DESC 'RFC22 |
|
62 |
|
56: international ISDN number' EQUALITY numericStringMatch SUBSTR numericSt |
|
63 |
|
ringSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} ) |
|
64 |
|
olcAttributeTypes: {22}( 2.5.4.26 NAME 'registeredAddress' DESC 'RFC2256: re |
|
65 |
|
gistered postal address' SUP postalAddress SYNTAX 1.3.6.1.4.1.1466.115.121. |
|
66 |
|
1.41 ) |
|
67 |
|
olcAttributeTypes: {23}( 2.5.4.27 NAME 'destinationIndicator' DESC 'RFC2256: |
|
68 |
|
destination indicator' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstring |
|
69 |
|
sMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} ) |
|
70 |
|
olcAttributeTypes: {24}( 2.5.4.28 NAME 'preferredDeliveryMethod' DESC 'RFC22 |
|
71 |
|
56: preferred delivery method' SYNTAX 1.3.6.1.4.1.1466.115.121.1.14 SINGLE- |
|
72 |
|
VALUE ) |
|
73 |
|
olcAttributeTypes: {25}( 2.5.4.29 NAME 'presentationAddress' DESC 'RFC2256: |
|
74 |
|
presentation address' EQUALITY presentationAddressMatch SYNTAX 1.3.6.1.4.1. |
|
75 |
|
1466.115.121.1.43 SINGLE-VALUE ) |
|
76 |
|
olcAttributeTypes: {26}( 2.5.4.30 NAME 'supportedApplicationContext' DESC 'R |
|
77 |
|
FC2256: supported application context' EQUALITY objectIdentifierMatch SYNTA |
|
78 |
|
X 1.3.6.1.4.1.1466.115.121.1.38 ) |
|
79 |
|
olcAttributeTypes: {27}( 2.5.4.31 NAME 'member' DESC 'RFC2256: member of a g |
|
80 |
|
roup' SUP distinguishedName ) |
|
81 |
|
olcAttributeTypes: {28}( 2.5.4.32 NAME 'owner' DESC 'RFC2256: owner (of the |
|
82 |
|
object)' SUP distinguishedName ) |
|
83 |
|
olcAttributeTypes: {29}( 2.5.4.33 NAME 'roleOccupant' DESC 'RFC2256: occupan |
|
84 |
|
t of role' SUP distinguishedName ) |
|
85 |
|
olcAttributeTypes: {30}( 2.5.4.36 NAME 'userCertificate' DESC 'RFC2256: X.50 |
|
86 |
|
9 user certificate, use ;binary' EQUALITY certificateExactMatch SYNTAX 1.3. |
|
87 |
|
6.1.4.1.1466.115.121.1.8 ) |
|
88 |
|
olcAttributeTypes: {31}( 2.5.4.37 NAME 'cACertificate' DESC 'RFC2256: X.509 |
|
89 |
|
CA certificate, use ;binary' EQUALITY certificateExactMatch SYNTAX 1.3.6.1. |
|
90 |
|
4.1.1466.115.121.1.8 ) |
|
91 |
|
olcAttributeTypes: {32}( 2.5.4.38 NAME 'authorityRevocationList' DESC 'RFC22 |
|
92 |
|
56: X.509 authority revocation list, use ;binary' SYNTAX 1.3.6.1.4.1.1466.1 |
|
93 |
|
15.121.1.9 ) |
|
94 |
|
olcAttributeTypes: {33}( 2.5.4.39 NAME 'certificateRevocationList' DESC 'RFC |
|
95 |
|
2256: X.509 certificate revocation list, use ;binary' SYNTAX 1.3.6.1.4.1.14 |
|
96 |
|
66.115.121.1.9 ) |
|
97 |
|
olcAttributeTypes: {34}( 2.5.4.40 NAME 'crossCertificatePair' DESC 'RFC2256: |
|
98 |
|
X.509 cross certificate pair, use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121 |
|
99 |
|
.1.10 ) |
|
100 |
|
olcAttributeTypes: {35}( 2.5.4.42 NAME ( 'givenName' 'gn' ) DESC 'RFC2256: f |
|
101 |
|
irst name(s) for which the entity is known by' SUP name ) |
|
102 |
|
olcAttributeTypes: {36}( 2.5.4.43 NAME 'initials' DESC 'RFC2256: initials of |
|
103 |
|
some or all of names, but not the surname(s).' SUP name ) |
|
104 |
|
olcAttributeTypes: {37}( 2.5.4.44 NAME 'generationQualifier' DESC 'RFC2256: |
|
105 |
|
name qualifier indicating a generation' SUP name ) |
|
106 |
|
olcAttributeTypes: {38}( 2.5.4.45 NAME 'x500UniqueIdentifier' DESC 'RFC2256: |
|
107 |
|
X.500 unique identifier' EQUALITY bitStringMatch SYNTAX 1.3.6.1.4.1.1466.1 |
|
108 |
|
15.121.1.6 ) |
|
109 |
|
olcAttributeTypes: {39}( 2.5.4.46 NAME 'dnQualifier' DESC 'RFC2256: DN quali |
|
110 |
|
fier' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR case |
|
111 |
|
IgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 ) |
|
112 |
|
olcAttributeTypes: {40}( 2.5.4.47 NAME 'enhancedSearchGuide' DESC 'RFC2256: |
|
113 |
|
enhanced search guide' SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 ) |
|
114 |
|
olcAttributeTypes: {41}( 2.5.4.48 NAME 'protocolInformation' DESC 'RFC2256: |
|
115 |
|
protocol information' EQUALITY protocolInformationMatch SYNTAX 1.3.6.1.4.1. |
|
116 |
|
1466.115.121.1.42 ) |
|
117 |
|
olcAttributeTypes: {42}( 2.5.4.50 NAME 'uniqueMember' DESC 'RFC2256: unique |
|
118 |
|
member of a group' EQUALITY uniqueMemberMatch SYNTAX 1.3.6.1.4.1.1466.115.1 |
|
119 |
|
21.1.34 ) |
|
120 |
|
olcAttributeTypes: {43}( 2.5.4.51 NAME 'houseIdentifier' DESC 'RFC2256: hous |
|
121 |
|
e identifier' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYN |
|
122 |
|
TAX 1.3.6.1.4.1.1466.115.121.1.15{32768} ) |
|
123 |
|
olcAttributeTypes: {44}( 2.5.4.52 NAME 'supportedAlgorithms' DESC 'RFC2256: |
|
124 |
|
supported algorithms' SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 ) |
|
125 |
|
olcAttributeTypes: {45}( 2.5.4.53 NAME 'deltaRevocationList' DESC 'RFC2256: |
|
126 |
|
delta revocation list; use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 ) |
|
127 |
|
olcAttributeTypes: {46}( 2.5.4.54 NAME 'dmdName' DESC 'RFC2256: name of DMD' |
|
128 |
|
SUP name ) |
|
129 |
|
olcAttributeTypes: {47}( 2.5.4.65 NAME 'pseudonym' DESC 'X.520(4th): pseudon |
|
130 |
|
ym for the object' SUP name ) |
|
131 |
|
olcAttributeTypes: {48}( 0.9.2342.19200300.100.1.3 NAME ( 'mail' 'rfc822Mail |
|
132 |
|
box' ) DESC 'RFC1274: RFC822 Mailbox' EQUALITY caseIgnoreIA5Match SUBST |
|
133 |
|
R caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} |
|
134 |
|
) |
|
135 |
|
olcAttributeTypes: {49}( 0.9.2342.19200300.100.1.25 NAME ( 'dc' 'domainCompo |
|
136 |
|
nent' ) DESC 'RFC1274/2247: domain component' EQUALITY caseIgnoreIA5Match S |
|
137 |
|
UBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SIN |
|
138 |
|
GLE-VALUE ) |
|
139 |
|
olcAttributeTypes: {50}( 0.9.2342.19200300.100.1.37 NAME 'associatedDomain' |
|
140 |
|
DESC 'RFC1274: domain associated with object' EQUALITY caseIgnoreIA5Match S |
|
141 |
|
UBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) |
|
142 |
|
olcAttributeTypes: {51}( 1.2.840.113549.1.9.1 NAME ( 'email' 'emailAddress' |
|
143 |
|
'pkcs9email' ) DESC 'RFC3280: legacy attribute for email addresses in DNs' |
|
144 |
|
EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3. |
|
145 |
|
6.1.4.1.1466.115.121.1.26{128} ) |
|
146 |
|
olcObjectClasses: {0}( 2.5.6.2 NAME 'country' DESC 'RFC2256: a country' SUP |
|
147 |
|
top STRUCTURAL MUST c MAY ( searchGuide $ description ) ) |
|
148 |
|
olcObjectClasses: {1}( 2.5.6.3 NAME 'locality' DESC 'RFC2256: a locality' SU |
|
149 |
|
P top STRUCTURAL MAY ( street $ seeAlso $ searchGuide $ st $ l $ descriptio |
|
150 |
|
n ) ) |
|
151 |
|
olcObjectClasses: {2}( 2.5.6.4 NAME 'organization' DESC 'RFC2256: an organiz |
|
152 |
|
ation' SUP top STRUCTURAL MUST o MAY ( userPassword $ searchGuide $ seeAlso |
|
153 |
|
$ businessCategory $ x121Address $ registeredAddress $ destinationIndicato |
|
154 |
|
r $ preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $ tel |
|
155 |
|
ephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $ street |
|
156 |
|
$ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName |
|
157 |
|
$ st $ l $ description ) ) |
|
158 |
|
olcObjectClasses: {3}( 2.5.6.5 NAME 'organizationalUnit' DESC 'RFC2256: an o |
|
159 |
|
rganizational unit' SUP top STRUCTURAL MUST ou MAY ( userPassword $ searchG |
|
160 |
|
uide $ seeAlso $ businessCategory $ x121Address $ registeredAddress $ desti |
|
161 |
|
nationIndicator $ preferredDeliveryMethod $ telexNumber $ teletexTerminalId |
|
162 |
|
entifier $ telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNu |
|
163 |
|
mber $ street $ postOfficeBox $ postalCode $ postalAddress $ physicalDelive |
|
164 |
|
ryOfficeName $ st $ l $ description ) ) |
|
165 |
|
olcObjectClasses: {4}( 2.5.6.6 NAME 'person' DESC 'RFC2256: a person' SUP to |
|
166 |
|
p STRUCTURAL MUST ( sn $ cn ) MAY ( userPassword $ telephoneNumber $ seeAls |
|
167 |
|
o $ description ) ) |
|
168 |
|
olcObjectClasses: {5}( 2.5.6.7 NAME 'organizationalPerson' DESC 'RFC2256: an |
|
169 |
|
organizational person' SUP person STRUCTURAL MAY ( title $ x121Address $ r |
|
170 |
|
egisteredAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNu |
|
171 |
|
mber $ teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumbe |
|
172 |
|
r $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $ posta |
|
173 |
|
lAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) ) |
|
174 |
|
olcObjectClasses: {6}( 2.5.6.8 NAME 'organizationalRole' DESC 'RFC2256: an o |
|
175 |
|
rganizational role' SUP top STRUCTURAL MUST cn MAY ( x121Address $ register |
|
176 |
|
edAddress $ destinationIndicator $ preferredDeliveryMethod $ telexNumber $ |
|
177 |
|
teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $ fac |
|
178 |
|
simileTelephoneNumber $ seeAlso $ roleOccupant $ preferredDeliveryMethod $ |
|
179 |
|
street $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOffic |
|
180 |
|
eName $ ou $ st $ l $ description ) ) |
|
181 |
|
olcObjectClasses: {7}( 2.5.6.9 NAME 'groupOfNames' DESC 'RFC2256: a group of |
|
182 |
|
names (DNs)' SUP top STRUCTURAL MUST ( member $ cn ) MAY ( businessCategor |
|
183 |
|
y $ seeAlso $ owner $ ou $ o $ description ) ) |
|
184 |
|
olcObjectClasses: {8}( 2.5.6.10 NAME 'residentialPerson' DESC 'RFC2256: an r |
|
185 |
|
esidential person' SUP person STRUCTURAL MUST l MAY ( businessCategory $ x1 |
|
186 |
|
21Address $ registeredAddress $ destinationIndicator $ preferredDeliveryMet |
|
187 |
|
hod $ telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internati |
|
188 |
|
onaliSDNNumber $ facsimileTelephoneNumber $ preferredDeliveryMethod $ stree |
|
189 |
|
t $ postOfficeBox $ postalCode $ postalAddress $ physicalDeliveryOfficeName |
|
190 |
|
$ st $ l ) ) |
|
191 |
|
olcObjectClasses: {9}( 2.5.6.11 NAME 'applicationProcess' DESC 'RFC2256: an |
|
192 |
|
application process' SUP top STRUCTURAL MUST cn MAY ( seeAlso $ ou $ l $ de |
|
193 |
|
scription ) ) |
|
194 |
|
olcObjectClasses: {10}( 2.5.6.12 NAME 'applicationEntity' DESC 'RFC2256: an |
|
195 |
|
application entity' SUP top STRUCTURAL MUST ( presentationAddress $ cn ) MA |
|
196 |
|
Y ( supportedApplicationContext $ seeAlso $ ou $ o $ l $ description ) ) |
|
197 |
|
olcObjectClasses: {11}( 2.5.6.13 NAME 'dSA' DESC 'RFC2256: a directory syste |
|
198 |
|
m agent (a server)' SUP applicationEntity STRUCTURAL MAY knowledgeInformati |
|
199 |
|
on ) |
|
200 |
|
olcObjectClasses: {12}( 2.5.6.14 NAME 'device' DESC 'RFC2256: a device' SUP |
|
201 |
|
top STRUCTURAL MUST cn MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ |
|
202 |
|
description ) ) |
|
203 |
|
olcObjectClasses: {13}( 2.5.6.15 NAME 'strongAuthenticationUser' DESC 'RFC22 |
|
204 |
|
56: a strong authentication user' SUP top AUXILIARY MUST userCertificate ) |
|
205 |
|
olcObjectClasses: {14}( 2.5.6.16 NAME 'certificationAuthority' DESC 'RFC2256 |
|
206 |
|
: a certificate authority' SUP top AUXILIARY MUST ( authorityRevocationList |
|
207 |
|
$ certificateRevocationList $ cACertificate ) MAY crossCertificatePair ) |
|
208 |
|
olcObjectClasses: {15}( 2.5.6.17 NAME 'groupOfUniqueNames' DESC 'RFC2256: a |
|
209 |
|
group of unique names (DN and Unique Identifier)' SUP top STRUCTURAL MUST ( |
|
210 |
|
uniqueMember $ cn ) MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ de |
|
211 |
|
scription ) ) |
|
212 |
|
olcObjectClasses: {16}( 2.5.6.18 NAME 'userSecurityInformation' DESC 'RFC225 |
|
213 |
|
6: a user security information' SUP top AUXILIARY MAY ( supportedAlgorithms |
|
214 |
|
) ) |
|
215 |
|
olcObjectClasses: {17}( 2.5.6.16.2 NAME 'certificationAuthority-V2' SUP cert |
|
216 |
|
ificationAuthority AUXILIARY MAY ( deltaRevocationList ) ) |
|
217 |
|
olcObjectClasses: {18}( 2.5.6.19 NAME 'cRLDistributionPoint' SUP top STRUCTU |
|
218 |
|
RAL MUST ( cn ) MAY ( certificateRevocationList $ authorityRevocationList $ |
|
219 |
|
deltaRevocationList ) ) |
|
220 |
|
olcObjectClasses: {19}( 2.5.6.20 NAME 'dmd' SUP top STRUCTURAL MUST ( dmdNam |
|
221 |
|
e ) MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $ x121Add |
|
222 |
|
ress $ registeredAddress $ destinationIndicator $ preferredDeliveryMethod $ |
|
223 |
|
telexNumber $ teletexTerminalIdentifier $ telephoneNumber $ internationali |
|
224 |
|
SDNNumber $ facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode |
|
225 |
|
$ postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) ) |
|
226 |
|
olcObjectClasses: {20}( 2.5.6.21 NAME 'pkiUser' DESC 'RFC2587: a PKI user' S |
|
227 |
|
UP top AUXILIARY MAY userCertificate ) |
|
228 |
|
olcObjectClasses: {21}( 2.5.6.22 NAME 'pkiCA' DESC 'RFC2587: PKI certificate |
|
229 |
|
authority' SUP top AUXILIARY MAY ( authorityRevocationList $ certificateRe |
|
230 |
|
vocationList $ cACertificate $ crossCertificatePair ) ) |
|
231 |
|
olcObjectClasses: {22}( 2.5.6.23 NAME 'deltaCRL' DESC 'RFC2587: PKI user' SU |
|
232 |
|
P top AUXILIARY MAY deltaRevocationList ) |
|
233 |
|
olcObjectClasses: {23}( 1.3.6.1.4.1.250.3.15 NAME 'labeledURIObject' DESC 'R |
|
234 |
|
FC2079: object that contains the URI attribute type' MAY ( labeledURI ) SUP |
|
235 |
|
top AUXILIARY ) |
|
236 |
|
olcObjectClasses: {24}( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObjec |
|
237 |
|
t' DESC 'RFC1274: simple security object' SUP top AUXILIARY MUST userPasswo |
|
238 |
|
rd ) |
|
239 |
|
olcObjectClasses: {25}( 1.3.6.1.4.1.1466.344 NAME 'dcObject' DESC 'RFC2247: |
|
240 |
|
domain component object' SUP top AUXILIARY MUST dc ) |
|
241 |
|
olcObjectClasses: {26}( 1.3.6.1.1.3.1 NAME 'uidObject' DESC 'RFC2377: uid ob |
|
242 |
|
ject' SUP top AUXILIARY MUST uid ) |
|
243 |
|
structuralObjectClass: olcSchemaConfig |
|
244 |
|
entryUUID: 38c549b0-fc43-1036-9076-ebf5d4043f34 |
|
245 |
|
creatorsName: cn=config |
|
246 |
|
createTimestamp: 20170713181706Z |
|
247 |
|
entryCSN: 20170713181706.283686Z#000000#000#000000 |
|
248 |
|
modifiersName: cn=config |
|
249 |
|
modifyTimestamp: 20170713181706Z |
File tests/ldap/prepare.sh added (mode: 100755) (index 0000000..7069302) |
|
1 |
|
#!/bin/bash |
|
2 |
|
|
|
3 |
|
# Wait till the server answers |
|
4 |
|
while [ 1 ]; do |
|
5 |
|
ldapsearch -x -P3 -s base -H ldap://${rg_ldap_addr}:${rg_ldap_port} &>/dev/null |
|
6 |
|
if [ "${?}" != "0" ]; then |
|
7 |
|
sleep .1 |
|
8 |
|
continue |
|
9 |
|
fi |
|
10 |
|
break |
|
11 |
|
done |
|
12 |
|
|
|
13 |
|
# All or nothing |
|
14 |
|
set -e |
|
15 |
|
|
|
16 |
|
echo "=== Set path to the database..." |
|
17 |
|
cat<<EOF | ldapadd -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
18 |
|
dn: olcDatabase={2}mdb,cn=config |
|
19 |
|
changeType: modify |
|
20 |
|
replace: olcDbDirectory |
|
21 |
|
olcDbDirectory: chroot-${rg_ldap_ns}/var/lib/ldap |
|
22 |
|
EOF |
|
23 |
|
|
|
24 |
|
|
|
25 |
|
# Seems this is not allowed |
|
26 |
|
#echo "=== Set log file..." |
|
27 |
|
#cat<<EOF | ldapadd -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
28 |
|
#dn: olcDatabase={2}mdb,cn=config |
|
29 |
|
#changeType: modify |
|
30 |
|
#replace: olcLogFile |
|
31 |
|
#olcLogFile: chroot-${rg_ldap_ns}/var/lib/ldap/slapd.log |
|
32 |
|
#EOF |
|
33 |
|
|
|
34 |
|
|
|
35 |
|
echo "=== Copying certificates and keys..." |
|
36 |
|
dst="chroot-${rg_ldap_ns}/etc/ssl" |
|
37 |
|
mkdir -p "${dst}/certs" |
|
38 |
|
cp ../ca/ldap/certs/cacert.pem "${dst}/certs/" |
|
39 |
|
cp ../ca/ldap/certs/localhost.pem "chroot-${rg_ldap_ns}/etc/openldap/" |
|
40 |
|
cp ../ca/ldap/private/localhost.key "chroot-${rg_ldap_ns}/etc/openldap/" |
|
41 |
|
|
|
42 |
|
|
|
43 |
|
echo "=== Changing ServerID..." |
|
44 |
|
cat <<EOF | ldapmodify -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
45 |
|
dn: cn=config |
|
46 |
|
changeType: modify |
|
47 |
|
replace: olcServerID |
|
48 |
|
olcServerID: ${rg_ldap_server_id} |
|
49 |
|
EOF |
|
50 |
|
|
|
51 |
|
|
|
52 |
|
echo "=== Loading schemas..." |
|
53 |
|
for s in cosine nis inetorgperson; do |
|
54 |
|
ldapadd -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock \ |
|
55 |
|
-f /etc/openldap/schema/${s}.ldif |
|
56 |
|
done |
|
57 |
|
|
|
58 |
|
|
|
59 |
|
echo "=== Enabling TLS..." |
|
60 |
|
cat<<EOF | ldapmodify -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
61 |
|
dn: cn=config |
|
62 |
|
replace: olcTLSCACertificateFile |
|
63 |
|
olcTLSCACertificateFile: ${PWD}/chroot-${rg_ldap_ns}/etc/ssl/certs/cacert.pem |
|
64 |
|
- |
|
65 |
|
replace: olcTLSCertificateKeyFile |
|
66 |
|
olcTLSCertificateKeyFile: ${PWD}/chroot-${rg_ldap_ns}/etc/openldap/localhost.key |
|
67 |
|
- |
|
68 |
|
replace: olcTLSCertificateFile |
|
69 |
|
olcTLSCertificateFile: ${PWD}/chroot-${rg_ldap_ns}/etc/openldap/localhost.pem |
|
70 |
|
EOF |
|
71 |
|
|
|
72 |
|
|
|
73 |
|
# http://www.openldap.org/doc/admin24/replication.html#N-Way%20Multi-Master |
|
74 |
|
echo "=== Adding syncrepl module and overlay..." |
|
75 |
|
cat<<EOF | ldapadd -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
76 |
|
dn: cn=module,cn=config |
|
77 |
|
objectClass: olcModuleList |
|
78 |
|
cn: module |
|
79 |
|
olcModuleLoad: syncprov |
|
80 |
|
|
|
81 |
|
dn: olcOverlay=syncprov,olcDatabase={2}mdb,cn=config |
|
82 |
|
objectClass: olcConfig |
|
83 |
|
objectClass: olcSyncProvConfig |
|
84 |
|
objectClass: olcOverlayConfig |
|
85 |
|
objectClass: top |
|
86 |
|
olcOverlay: syncprov |
|
87 |
|
EOF |
|
88 |
|
|
|
89 |
|
|
|
90 |
|
echo "=== Adding memberOf module and overlay..." |
|
91 |
|
cat<<EOF | ldapadd -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
92 |
|
dn: cn=module,cn=config |
|
93 |
|
cn: module |
|
94 |
|
objectclass: olcModuleList |
|
95 |
|
objectclass: top |
|
96 |
|
olcmoduleload: memberof |
|
97 |
|
|
|
98 |
|
dn: olcOverlay=memberof,olcDatabase={2}mdb,cn=config |
|
99 |
|
objectClass: olcConfig |
|
100 |
|
objectClass: olcMemberOf |
|
101 |
|
objectClass: olcOverlayConfig |
|
102 |
|
objectClass: top |
|
103 |
|
olcOverlay: memberof |
|
104 |
|
EOF |
|
105 |
|
|
|
106 |
|
|
|
107 |
|
echo "=== Adding refInt module and overlay..." |
|
108 |
|
cat<<EOF | ldapadd -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
109 |
|
dn: cn=module,cn=config |
|
110 |
|
cn: module |
|
111 |
|
objectclass: olcModuleList |
|
112 |
|
objectclass: top |
|
113 |
|
olcmoduleload: refint |
|
114 |
|
|
|
115 |
|
dn: olcOverlay=refint,olcDatabase={2}mdb,cn=config |
|
116 |
|
objectClass: olcConfig |
|
117 |
|
objectClass: olcOverlayConfig |
|
118 |
|
objectClass: olcRefintConfig |
|
119 |
|
objectClass: top |
|
120 |
|
olcOverlay: refint |
|
121 |
|
olcRefintAttribute: memberof member manager owner |
|
122 |
|
EOF |
|
123 |
|
|
|
124 |
|
|
|
125 |
|
cat <<EOF | ldapmodify -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
126 |
|
dn: olcDatabase={2}mdb,cn=config |
|
127 |
|
replace: olcRootPW |
|
128 |
|
olcRootPW: ${rg_ldap_pass} |
|
129 |
|
EOF |
|
130 |
|
|
|
131 |
|
|
|
132 |
|
if [ "${rg_ldap_producer_url}" != "" ]; then |
|
133 |
|
echo "=== We are consumer for ${rg_ldap_producer_url}!" |
|
134 |
|
cat <<EOF | ldapmodify -Y EXTERNAL -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
135 |
|
dn: olcDatabase={2}mdb,cn=config |
|
136 |
|
changeType: modify |
|
137 |
|
add: olcLimits |
|
138 |
|
olcLimits: dn.exact="cn=Manager,dc=my-domain,dc=com" time.soft=unlimited time.hard=unlimited size.soft=unlimited size.hard=unlimited |
|
139 |
|
- |
|
140 |
|
add: olcSyncRepl |
|
141 |
|
olcSyncRepl: rid=${rg_ldap_producer_rid} |
|
142 |
|
provider=${rg_ldap_producer_url} |
|
143 |
|
binddn="cn=Manager,dc=my-domain,dc=com" |
|
144 |
|
bindmethod=simple |
|
145 |
|
credentials=${rg_ldap_pass} |
|
146 |
|
searchbase="dc=my-domain,dc=com" |
|
147 |
|
type=refreshAndPersist |
|
148 |
|
retry="5 5 300 5" timeout=3 |
|
149 |
|
- |
|
150 |
|
add: olcMirrorMode |
|
151 |
|
olcMirrorMode: TRUE |
|
152 |
|
EOF |
|
153 |
|
fi |
|
154 |
|
|
|
155 |
|
if [ "${rg_ldap_add_data}" = "0" ]; then |
|
156 |
|
touch "chroot-${rg_ldap_ns}/prep.done" |
|
157 |
|
exit 0 |
|
158 |
|
fi |
|
159 |
|
|
|
160 |
|
cat <<EOF | ldapadd -x -w${rg_ldap_pass} -D "cn=Manager,dc=my-domain,dc=com" -H ldapi://ldapi-${rg_ldap_ns}.sock |
|
161 |
|
dn: dc=my-domain,dc=com |
|
162 |
|
objectClass: top |
|
163 |
|
objectClass: domain |
|
164 |
|
dc: my-domain |
|
165 |
|
|
|
166 |
|
dn: cn=Manager,dc=my-domain,dc=com |
|
167 |
|
objectClass: organizationalRole |
|
168 |
|
cn: Manager |
|
169 |
|
|
|
170 |
|
dn: ou=People,dc=my-domain,dc=com |
|
171 |
|
objectClass: organizationalUnit |
|
172 |
|
ou: People |
|
173 |
|
|
|
174 |
|
dn: ou=Group,dc=my-domain,dc=com |
|
175 |
|
objectClass: organizationalUnit |
|
176 |
|
ou: Group |
|
177 |
|
|
|
178 |
|
dn: cn=posix_group1,ou=Group,dc=my-domain,dc=com |
|
179 |
|
cn: posix_group1 |
|
180 |
|
objectClass: top |
|
181 |
|
objectClass: posixGroup |
|
182 |
|
gidNumber: 100000 |
|
183 |
|
|
|
184 |
|
dn: cn=posix_group2,ou=Group,dc=my-domain,dc=com |
|
185 |
|
cn: posix_group2 |
|
186 |
|
objectClass: top |
|
187 |
|
objectClass: posixGroup |
|
188 |
|
gidNumber: 100001 |
|
189 |
|
|
|
190 |
|
dn: uid=user1-${rg_ldap_user_key},ou=People,dc=my-domain,dc=com |
|
191 |
|
objectClass: top |
|
192 |
|
objectClass: inetOrgPerson |
|
193 |
|
objectClass: shadowAccount |
|
194 |
|
objectClass: posixAccount |
|
195 |
|
uid: user1-${rg_ldap_user_key} |
|
196 |
|
userPassword: ${rg_ldap_user_pass} |
|
197 |
|
sn: surname-user1-${rg_ldap_user_key} |
|
198 |
|
gn: givenname-user1-${rg_ldap_user_key} |
|
199 |
|
cn: User1 ${rg_ldap_user_key} |
|
200 |
|
uidNumber: 100000 |
|
201 |
|
gidNumber: 100000 |
|
202 |
|
mail: user1-${rg_ldap_user_key}@my-domain.com |
|
203 |
|
mail: user1-${rg_ldap_user_key}-backup@my-domain.com |
|
204 |
|
homeDirectory: /home/user1-${rg_ldap_user_key} |
|
205 |
|
description: This is a description of user user1 |
|
206 |
|
|
|
207 |
|
dn: uid=user2-${rg_ldap_user_key}-uid,ou=People,dc=my-domain,dc=com |
|
208 |
|
objectClass: top |
|
209 |
|
objectClass: inetOrgPerson |
|
210 |
|
objectClass: shadowAccount |
|
211 |
|
objectClass: posixAccount |
|
212 |
|
uid: user2-${rg_ldap_user_key}-uid |
|
213 |
|
userPassword: ${rg_ldap_user_pass} |
|
214 |
|
sn: surname-user2-${rg_ldap_user_key} |
|
215 |
|
gn: givenname-user2-${rg_ldap_user_key} |
|
216 |
|
cn: User2 ${rg_ldap_user_key} |
|
217 |
|
uidNumber: 100001 |
|
218 |
|
gidNumber: 100001 |
|
219 |
|
mail: user2-${rg_ldap_user_key}@my-domain.com |
|
220 |
|
mail: user2-${rg_ldap_user_key}-backup@my-domain.com |
|
221 |
|
homeDirectory: /home/user2-${rg_ldap_user_key} |
|
222 |
|
description: user2-${rg_ldap_user_key} |
|
223 |
|
|
|
224 |
|
dn: uid=user3-${rg_ldap_user_key},ou=People,dc=my-domain,dc=com |
|
225 |
|
objectClass: top |
|
226 |
|
objectClass: inetOrgPerson |
|
227 |
|
uid: user3-${rg_ldap_user_key} |
|
228 |
|
userPassword: ${rg_ldap_user_pass} |
|
229 |
|
sn: surname-user3-${rg_ldap_user_key} |
|
230 |
|
cn: User3 ${rg_ldap_user_key} |
|
231 |
|
mail: user3-${rg_ldap_user_key}@my-domain.com |
|
232 |
|
mail: user3-${rg_ldap_user_key}-backup@my-domain.com |
|
233 |
|
|
|
234 |
|
dn: uid=user4-${rg_ldap_user_key},ou=People,dc=my-domain,dc=com |
|
235 |
|
objectClass: top |
|
236 |
|
objectClass: inetOrgPerson |
|
237 |
|
uid: user4-${rg_ldap_user_key} |
|
238 |
|
userPassword: ${rg_ldap_user_pass} |
|
239 |
|
sn: surname-user4-${rg_ldap_user_key} |
|
240 |
|
gn: givenname-user4-${rg_ldap_user_key} |
|
241 |
|
cn: User4 ${rg_ldap_user_key} |
|
242 |
|
mail: user4-${rg_ldap_user_key}@my-domain.com |
|
243 |
|
mail: user4-${rg_ldap_user_key}-backup@my-domain.com |
|
244 |
|
|
|
245 |
|
# groupOfNames must be created after creating the users, else 'memberOf' will not be set |
|
246 |
|
dn: cn=group1,ou=Group,dc=my-domain,dc=com |
|
247 |
|
objectClass: top |
|
248 |
|
objectClass: groupOfNames |
|
249 |
|
cn: group1 |
|
250 |
|
member: uid=user1-${rg_ldap_user_key},ou=People,dc=my-domain,dc=com |
|
251 |
|
member: uid=user2-${rg_ldap_user_key}-uid,ou=People,dc=my-domain,dc=com |
|
252 |
|
member: uid=invalid,ou=People,dc=my-domain,dc=com |
|
253 |
|
|
|
254 |
|
dn: cn=group_unique,ou=Group,dc=my-domain,dc=com |
|
255 |
|
objectClass: top |
|
256 |
|
objectClass: groupOfUniqueNames |
|
257 |
|
cn: group_unique |
|
258 |
|
uniqueMember: uid=user2-${rg_ldap_user_key}-uid,ou=People,dc=my-domain,dc=com |
|
259 |
|
uniqueMember: uid=invalid2,ou=People,dc=my-domain,dc=com |
|
260 |
|
|
|
261 |
|
dn: cn=Admins,ou=Group,dc=my-domain,dc=com |
|
262 |
|
objectClass: top |
|
263 |
|
objectClass: groupOfNames |
|
264 |
|
cn: Admins |
|
265 |
|
member: uid=user1-${rg_ldap_user_key},ou=People,dc=my-domain,dc=com |
|
266 |
|
EOF |
|
267 |
|
|
|
268 |
|
|
|
269 |
|
# Signal that preparation is ready |
|
270 |
|
touch "chroot-${rg_ldap_ns}/prep.done" |