test044-dynlist revision 1.1.1.4
1#! /bin/sh
2## This work is part of OpenLDAP Software <http://www.openldap.org/>.
3##
4## Copyright 1998-2014 The OpenLDAP Foundation.
5## All rights reserved.
6##
7## Redistribution and use in source and binary forms, with or without
8## modification, are permitted only as authorized by the OpenLDAP
9## Public License.
10##
11## A copy of this license is available in the file LICENSE in the
12## top-level directory of the distribution or, alternatively, at
13## <http://www.OpenLDAP.org/license.html>.
14
15echo "running defines.sh"
16. $SRCDIR/scripts/defines.sh
17
18if test $DYNLIST = "dynlistno" ; then 
19	echo "dynlist overlay not available, test skipped"
20	exit 0
21fi 
22
23if test $BACKEND = ldif ; then
24	# dynlist+ldif fails because back-ldif lacks bi_op_compare()
25	echo "$BACKEND backend unsuitable for dynlist overlay, test skipped"
26	exit 0
27fi
28
29mkdir -p $TESTDIR $DBDIR1
30
31$SLAPPASSWD -g -n >$CONFIGPWF
32echo "rootpw `$SLAPPASSWD -T $CONFIGPWF`" >$TESTDIR/configpw.conf
33
34if test $MONITORDB != no ; then
35	DBIX=2
36else
37	DBIX=1
38fi
39
40echo "Running slapadd to build slapd database..."
41. $CONFFILTER $BACKEND $MONITORDB < $MCONF > $ADDCONF
42$SLAPADD -f $ADDCONF -l $LDIFORDERED
43RC=$?
44if test $RC != 0 ; then
45	echo "slapadd failed ($RC)!"
46	exit $RC
47fi
48
49. $CONFFILTER $BACKEND $MONITORDB < $DYNLISTCONF > $CONF1
50
51echo "Starting slapd on TCP/IP port $PORT1..."
52$SLAPD -f $CONF1 -h $URI1 -d $LVL $TIMING > $LOG1 2>&1 &
53PID=$!
54if test $WAIT != 0 ; then
55    echo PID $PID
56    read foo
57fi
58KILLPIDS="$PID"
59
60sleep 1
61
62echo "Testing slapd searching..."
63for i in 0 1 2 3 4 5; do
64	$LDAPSEARCH -s base -b "$MONITOR" -h $LOCALHOST -p $PORT1 \
65		'(objectclass=*)' > /dev/null 2>&1
66	RC=$?
67	if test $RC = 0 ; then
68		break
69	fi
70	echo "Waiting 5 seconds for slapd to start..."
71	sleep 5
72done
73
74if test $RC != 0 ; then
75	echo "ldapsearch failed ($RC)!"
76	test $KILLSERVERS != no && kill -HUP $KILLPIDS
77	exit $RC
78fi
79
80cat /dev/null > $SEARCHOUT
81
82LISTDN="ou=Dynamic Lists,$BASEDN"
83echo "Adding a dynamic list..."
84$LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
85	> $TESTOUT 2>&1 << EOMODS
86dn: $LISTDN
87objectClass: organizationalUnit
88ou: Dynamic Lists
89
90dn: cn=Dynamic List,$LISTDN
91objectClass: groupOfURLs
92cn: Dynamic List
93memberURL: ldap:///ou=People,${BASEDN}?cn,mail?sub?(objectClass=person)
94EOMODS
95
96echo "Testing list search of all attrs..."
97echo "# Testing list search of all attrs..." >> $SEARCHOUT
98$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
99	'(cn=Dynamic List)' '*' \
100	>> $SEARCHOUT 2>&1
101RC=$?
102if test $RC != 0 ; then
103	echo "ldapsearch failed ($RC)!"
104	test $KILLSERVERS != no && kill -HUP $KILLPIDS
105	exit $RC
106fi
107
108echo "Testing list search of a listed attr..."
109echo "# Testing list search of a listed attr..." >> $SEARCHOUT
110$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
111	'(cn=Dynamic List)' mail \
112	>> $SEARCHOUT 2>&1
113RC=$?
114if test $RC != 0 ; then
115	echo "ldapsearch failed ($RC)!"
116	test $KILLSERVERS != no && kill -HUP $KILLPIDS
117	exit $RC
118fi
119
120echo "Testing list search of a non-listed attr..."
121echo "# Testing list search of a non-listed attr..." >> $SEARCHOUT
122$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
123	'(cn=Dynamic List)' objectClass \
124	>> $SEARCHOUT 2>&1
125RC=$?
126if test $RC != 0 ; then
127	echo "ldapsearch failed ($RC)!"
128	test $KILLSERVERS != no && kill -HUP $KILLPIDS
129	exit $RC
130fi
131
132echo "Testing list search with (critical) manageDSAit..."
133echo "# Testing list search with (critical) manageDSAit..." >> $SEARCHOUT
134$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 -MM \
135	'(cn=Dynamic List)' '*' \
136	>> $SEARCHOUT 2>&1
137RC=$?
138if test $RC != 0 ; then
139	echo "ldapsearch failed ($RC)!"
140	test $KILLSERVERS != no && kill -HUP $KILLPIDS
141	exit $RC
142fi
143
144echo "Testing list compare..."
145echo "# Testing list compare..." >> $SEARCHOUT
146$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
147	"cn=Dynamic List,$LISTDN" "cn:Bjorn Jensen" \
148	>> $SEARCHOUT 2>&1
149RC=$?
150case $RC in
1515)
152	echo "ldapcompare returned FALSE ($RC)!"
153	test $KILLSERVERS != no && kill -HUP $KILLPIDS
154	exit $RC
155	;;
1566)
157	echo "ldapcompare returned TRUE ($RC)"
158	;;
1590)
160	echo "ldapcompare returned success ($RC)!"
161	test $KILLSERVERS != no && kill -HUP $KILLPIDS
162	exit -1
163	;;
164*)
165	echo "ldapcompare failed ($RC)!"
166	test $KILLSERVERS != no && kill -HUP $KILLPIDS
167	exit $RC
168	;;
169esac
170echo "" >> $SEARCHOUT
171
172echo "Testing list compare (should return FALSE)..."
173echo "# Testing list compare (should return FALSE)..." >> $SEARCHOUT
174$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
175	"cn=Dynamic List,$LISTDN" "cn:FALSE" \
176	>> $SEARCHOUT 2>&1
177RC=$?
178case $RC in
1795)
180	echo "ldapcompare returned FALSE ($RC)"
181	;;
1826)
183	echo "ldapcompare returned TRUE ($RC)!"
184	test $KILLSERVERS != no && kill -HUP $KILLPIDS
185	exit $RC
186	;;
1870)
188	echo "ldapcompare returned success ($RC)!"
189	test $KILLSERVERS != no && kill -HUP $KILLPIDS
190	exit -1
191	;;
192*)
193	echo "ldapcompare failed ($RC)!"
194	test $KILLSERVERS != no && kill -HUP $KILLPIDS
195	exit $RC
196	;;
197esac
198echo "" >> $SEARCHOUT
199
200echo "Testing list compare (should return UNDEFINED)..."
201echo "# Testing list compare (should return UNDEFINED)..." >> $SEARCHOUT
202$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
203	"cn=Dynamic List,$LISTDN" "dc:UNDEFINED" \
204	>> $SEARCHOUT 2>&1
205RC=$?
206case $RC in
2075)
208	echo "ldapcompare returned FALSE ($RC)!"
209	test $KILLSERVERS != no && kill -HUP $KILLPIDS
210	exit $RC
211	;;
2126)
213	echo "ldapcompare returned TRUE ($RC)!"
214	test $KILLSERVERS != no && kill -HUP $KILLPIDS
215	exit $RC
216	;;
21716|32)
218	echo "ldapcompare returned UNDEFINED ($RC)"
219	;;
2200)
221	echo "ldapcompare returned success ($RC)!"
222	test $KILLSERVERS != no && kill -HUP $KILLPIDS
223	exit -1
224	;;
225*)
226	echo "ldapcompare failed ($RC)"
227	;;
228esac
229echo "" >> $SEARCHOUT
230
231echo "Testing list compare with manageDSAit..."
232echo "# Testing list compare with manageDSAit..." >> $SEARCHOUT
233$LDAPCOMPARE -h $LOCALHOST -p $PORT1 -MM \
234	"cn=Dynamic List,$LISTDN" "cn:Bjorn Jensen" \
235	>> $SEARCHOUT 2>&1
236RC=$?
237case $RC in
2385)
239	echo "ldapcompare returned FALSE ($RC)"
240	;;
2416)
242	echo "ldapcompare returned TRUE ($RC)!"
243	test $KILLSERVERS != no && kill -HUP $KILLPIDS
244	exit $RC
245	;;
2460)
247	echo "ldapcompare returned success ($RC)!"
248	test $KILLSERVERS != no && kill -HUP $KILLPIDS
249	exit -1
250	;;
251*)
252	echo "ldapcompare failed ($RC)!"
253	test $KILLSERVERS != no && kill -HUP $KILLPIDS
254	exit $RC
255	;;
256esac
257echo "" >> $SEARCHOUT
258
259echo "Reconfiguring slapd..."
260$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
261	$TESTOUT 2>&1 << EOMODS
262version: 1
263dn: olcOverlay={0}dynlist,olcDatabase={$DBIX}$BACKEND,cn=config
264changetype: modify
265delete: olcDLattrSet
266olcDLattrSet: {0}
267-
268add: olcDLattrSet
269olcDLattrSet: groupOfURLs memberURL sn:cn mail
270-
271EOMODS
272
273echo "==========================================================" >> $LOG1
274
275echo "Testing attribute mapping"
276
277echo "Testing list search of all (mapped) attrs..."
278echo "# Testing list search of all (mapped) attrs..." >> $SEARCHOUT
279$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
280	'(cn=Dynamic List)' '*' \
281	>> $SEARCHOUT 2>&1
282RC=$?
283if test $RC != 0 ; then
284	echo "ldapsearch failed ($RC)!"
285	test $KILLSERVERS != no && kill -HUP $KILLPIDS
286	exit $RC
287fi
288
289echo "Testing list search of a (mapped) listed attr..."
290echo "# Testing list search of a (mapped) listed attr..." >> $SEARCHOUT
291$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
292	'(cn=Dynamic List)' sn \
293	>> $SEARCHOUT 2>&1
294RC=$?
295if test $RC != 0 ; then
296	echo "ldapsearch failed ($RC)!"
297	test $KILLSERVERS != no && kill -HUP $KILLPIDS
298	exit $RC
299fi
300
301echo "Testing list search of a (n unmapped) listed attr..."
302echo "# Testing list search of a (n unmapped) listed attr..." >> $SEARCHOUT
303$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
304	'(cn=Dynamic List)' mail \
305	>> $SEARCHOUT 2>&1
306RC=$?
307if test $RC != 0 ; then
308	echo "ldapsearch failed ($RC)!"
309	test $KILLSERVERS != no && kill -HUP $KILLPIDS
310	exit $RC
311fi
312
313echo "Testing list compare (mapped attrs) ..."
314echo "# Testing list compare (mapped attrs) ..." >> $SEARCHOUT
315$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
316	"cn=Dynamic List,$LISTDN" "sn:Bjorn Jensen" \
317	>> $SEARCHOUT 2>&1
318RC=$?
319case $RC in
3205)
321	echo "ldapcompare returned FALSE ($RC)!"
322	test $KILLSERVERS != no && kill -HUP $KILLPIDS
323	exit $RC
324	;;
3256)
326	echo "ldapcompare returned TRUE ($RC)"
327	;;
3280)
329	echo "ldapcompare returned success ($RC)!"
330	test $KILLSERVERS != no && kill -HUP $KILLPIDS
331	exit -1
332	;;
333*)
334	echo "ldapcompare failed ($RC)!"
335	test $KILLSERVERS != no && kill -HUP $KILLPIDS
336	exit $RC
337	;;
338esac
339echo "" >> $SEARCHOUT
340
341echo "Testing list compare (mapped attrs; should return FALSE)..."
342echo "# Testing list compare (mapped attrs; should return FALSE)..." >> $SEARCHOUT
343$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
344	"cn=Dynamic List,$LISTDN" "sn:FALSE" \
345	>> $SEARCHOUT 2>&1
346RC=$?
347case $RC in
3485)
349	echo "ldapcompare returned FALSE ($RC)"
350	;;
3516)
352	echo "ldapcompare returned TRUE ($RC)!"
353	test $KILLSERVERS != no && kill -HUP $KILLPIDS
354	exit $RC
355	;;
3560)
357	echo "ldapcompare returned success ($RC)!"
358	test $KILLSERVERS != no && kill -HUP $KILLPIDS
359	exit -1
360	;;
361*)
362	echo "ldapcompare failed ($RC)!"
363	test $KILLSERVERS != no && kill -HUP $KILLPIDS
364	exit $RC
365	;;
366esac
367echo "" >> $SEARCHOUT
368
369echo "Reconfiguring slapd..."
370$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
371	$TESTOUT 2>&1 << EOMODS
372version: 1
373dn: olcOverlay={0}dynlist,olcDatabase={$DBIX}$BACKEND,cn=config
374changetype: modify
375delete: olcDLattrSet
376olcDLattrSet: {0}
377-
378add: olcDLattrSet
379olcDLattrSet: groupOfURLs memberURL member
380-
381EOMODS
382
383echo "==========================================================" >> $LOG1
384
385echo "Adding a dynamic list..."
386$LDAPADD -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
387	> $TESTOUT 2>&1 << EOMODS
388dn: cn=Dynamic List of Members,$LISTDN
389objectClass: groupOfURLs
390cn: Dynamic List of Members
391memberURL: ldap:///ou=People,${BASEDN}??sub?(objectClass=person)
392EOMODS
393
394echo "Testing list search of all attrs..."
395echo "# Testing list search of all attrs..." >> $SEARCHOUT
396$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
397	'(cn=Dynamic List of Members)' '*' \
398	>> $SEARCHOUT 2>&1
399RC=$?
400if test $RC != 0 ; then
401	echo "ldapsearch failed ($RC)!"
402	test $KILLSERVERS != no && kill -HUP $KILLPIDS
403	exit $RC
404fi
405
406echo "Testing list search of a listed attr..."
407echo "# Testing list search of a listed attr..." >> $SEARCHOUT
408$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
409	'(cn=Dynamic List of Members)' member \
410	>> $SEARCHOUT 2>&1
411RC=$?
412if test $RC != 0 ; then
413	echo "ldapsearch failed ($RC)!"
414	test $KILLSERVERS != no && kill -HUP $KILLPIDS
415	exit $RC
416fi
417
418echo "Testing list search of a non-listed attr..."
419echo "# Testing list search of a non-listed attr..." >> $SEARCHOUT
420$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
421	'(cn=Dynamic List of Members)' objectClass \
422	>> $SEARCHOUT 2>&1
423RC=$?
424if test $RC != 0 ; then
425	echo "ldapsearch failed ($RC)!"
426	test $KILLSERVERS != no && kill -HUP $KILLPIDS
427	exit $RC
428fi
429
430echo "Testing list search with (critical) manageDSAit..."
431echo "# Testing list search with (critical) manageDSAit..." >> $SEARCHOUT
432$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 -MM \
433	'(&(cn=Dynamic List of Members)(objectClass=groupOfURLs))' '*' \
434	>> $SEARCHOUT 2>&1
435RC=$?
436if test $RC != 0 ; then
437	echo "ldapsearch failed ($RC)!"
438	test $KILLSERVERS != no && kill -HUP $KILLPIDS
439	exit $RC
440fi
441
442CMPDN="$BJORNSDN"
443echo "Testing list compare..."
444echo "# Testing list compare..." >> $SEARCHOUT
445$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
446	"cn=Dynamic List of Members,$LISTDN" "member:$CMPDN" \
447	>> $SEARCHOUT 2>&1
448RC=$?
449case $RC in
4505)
451	echo "ldapcompare returned FALSE ($RC)!"
452	test $KILLSERVERS != no && kill -HUP $KILLPIDS
453	exit $RC
454	;;
4556)
456	echo "ldapcompare returned TRUE ($RC)"
457	;;
4580)
459	echo "ldapcompare returned success ($RC)!"
460	test $KILLSERVERS != no && kill -HUP $KILLPIDS
461	exit -1
462	;;
463*)
464	echo "ldapcompare failed ($RC)!"
465	test $KILLSERVERS != no && kill -HUP $KILLPIDS
466	exit $RC
467	;;
468esac
469echo "" >> $SEARCHOUT
470
471echo "Testing list compare (should return FALSE)..."
472echo "# Testing list compare (should return FALSE)..." >> $SEARCHOUT
473$LDAPCOMPARE -h $LOCALHOST -p $PORT1 \
474	"cn=Dynamic List of Members,$LISTDN" "member:cn=Foo Bar" \
475	>> $SEARCHOUT 2>&1
476RC=$?
477case $RC in
4785)
479	echo "ldapcompare returned FALSE ($RC)"
480	;;
4816)
482	echo "ldapcompare returned TRUE ($RC)!"
483	test $KILLSERVERS != no && kill -HUP $KILLPIDS
484	exit $RC
485	;;
4860)
487	echo "ldapcompare returned success ($RC)!"
488	test $KILLSERVERS != no && kill -HUP $KILLPIDS
489	exit -1
490	;;
491*)
492	echo "ldapcompare failed ($RC)!"
493	test $KILLSERVERS != no && kill -HUP $KILLPIDS
494	exit $RC
495	;;
496esac
497echo "" >> $SEARCHOUT
498
499echo "Testing list compare with manageDSAit..."
500echo "# Testing list compare with manageDSAit..." >> $SEARCHOUT
501$LDAPCOMPARE -h $LOCALHOST -p $PORT1 -MM \
502	"cn=Dynamic List,$LISTDN" "member:$CMPDN" \
503	>> $SEARCHOUT 2>&1
504RC=$?
505case $RC in
5065)
507	echo "ldapcompare returned FALSE ($RC)"
508	;;
5096)
510	echo "ldapcompare returned TRUE ($RC)!"
511	test $KILLSERVERS != no && kill -HUP $KILLPIDS
512	exit $RC
513	;;
5140)
515	echo "ldapcompare returned success ($RC)!"
516	test $KILLSERVERS != no && kill -HUP $KILLPIDS
517	exit -1
518	;;
519*)
520	echo "ldapcompare failed ($RC)!"
521	test $KILLSERVERS != no && kill -HUP $KILLPIDS
522	exit $RC
523	;;
524esac
525echo "" >> $SEARCHOUT
526
527echo "==========================================================" >> $LOG1
528
529echo "Testing dgIdentity..."
530
531# Set ACL, require authentication to get list contents
532$LDAPMODIFY -x -D cn=config -h $LOCALHOST -p $PORT1 -y $CONFIGPWF > \
533	$TESTOUT 2>&1 << EOMODS
534version: 1
535dn: olcDatabase={$DBIX}$BACKEND,cn=config
536changetype: modify
537add: olcAccess
538olcAccess: to dn.base="cn=Dynamic List of Members,$LISTDN" by * read
539olcAccess: to * by users read by * search
540EOMODS
541
542echo "Testing list search without dgIdentity..."
543echo "# Testing list search without dgIdentity..." >> $SEARCHOUT
544$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
545	'(cn=Dynamic List of Members)' '*' \
546	>> $SEARCHOUT 2>&1
547RC=$?
548if test $RC != 0 ; then
549	echo "ldapsearch failed ($RC)!"
550	test $KILLSERVERS != no && kill -HUP $KILLPIDS
551	exit $RC
552fi
553
554$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
555	> $TESTOUT 2>&1 << EOMODS
556dn: cn=Dynamic List of Members,$LISTDN
557changetype: modify
558add: objectClass
559objectClass: dgIdentityAux
560-
561add: dgIdentity
562dgIdentity: $CMPDN
563EOMODS
564
565echo "Testing list search with dgIdentity..."
566echo "# Testing list search with dgIdentity..." >> $SEARCHOUT
567$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
568	'(cn=Dynamic List of Members)' '*' \
569	>> $SEARCHOUT 2>&1
570RC=$?
571if test $RC != 0 ; then
572	echo "ldapsearch failed ($RC)!"
573	test $KILLSERVERS != no && kill -HUP $KILLPIDS
574	exit $RC
575fi
576
577echo "Testing dgAuthz..."
578
579CMPDN="cn=Bjorn Jensen,ou=Information Technology Division,ou=People,$BASEDN"
580$LDAPMODIFY -v -D "$MANAGERDN" -h $LOCALHOST -p $PORT1 -w $PASSWD \
581	> $TESTOUT 2>&1 << EOMODS
582dn: cn=Dynamic List of Members,$LISTDN
583changetype: modify
584add: dgAuthz
585dgAuthz: dn:$BABSDN
586EOMODS
587
588echo "Testing list search with dgIdentity and dgAuthz anonymously..."
589echo "# Testing list search with dgIdentity and dgAuthz anonymously..." >> $SEARCHOUT
590$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
591	'(cn=Dynamic List of Members)' '*' \
592	>> $SEARCHOUT 2>&1
593RC=$?
594if test $RC != 0 ; then
595	echo "ldapsearch failed ($RC)!"
596	test $KILLSERVERS != no && kill -HUP $KILLPIDS
597	exit $RC
598fi
599
600echo "Testing list search with dgIdentity and dgAuthz as the authorized identity..."
601echo "# Testing list search with dgIdentity and dgAuthz as the authorized identity..." >> $SEARCHOUT
602$LDAPSEARCH -S "" -b "$LISTDN" -h $LOCALHOST -p $PORT1 \
603	-D "$BABSDN" -w bjensen \
604	'(cn=Dynamic List of Members)' '*' \
605	>> $SEARCHOUT 2>&1
606RC=$?
607if test $RC != 0 ; then
608	echo "ldapsearch failed ($RC)!"
609	test $KILLSERVERS != no && kill -HUP $KILLPIDS
610	exit $RC
611fi
612
613test $KILLSERVERS != no && kill -HUP $KILLPIDS
614
615LDIF=$DYNLISTOUT
616
617echo "Filtering ldapsearch results..."
618$LDIFFILTER < $SEARCHOUT > $SEARCHFLT
619echo "Filtering original ldif used to create database..."
620$LDIFFILTER < $LDIF > $LDIFFLT
621echo "Comparing filter output..."
622$CMP $SEARCHFLT $LDIFFLT > $CMPOUT
623
624if test $? != 0 ; then
625	echo "Comparison failed"
626	exit 1
627fi
628
629echo ">>>>> Test succeeded"
630
631test $KILLSERVERS != no && wait
632
633exit 0
634