From Free IPA
Contents |
[edit]
Introduction
In the following all necessary files for for the IPA sudo policy are listed and described.
[edit]
XML Policy file for sudo
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ipa xmlns="http://freeipa.org/xml/rng/sudo/sudoers/1.0">
3 <metadata>
4 <name>simple sudoers example, allowing mount/umount of a CD-ROM</name>
5 <author>sbose@redhat.com</author>
6 <version>0.7071</version>
7 <RNGfile>sudoers.rng</RNGfile>
8 <XSLTfile>sudoers.xslt</XSLTfile>
9 </metadata>
10
11 <ipaconfig>
12 <sudoers>
13 <subject><name>abc</name><type>netgroup</type></subject>
14 <command><path>/sbin/umount /CDROM</path><tag>NOPASSWD</tag><runas>root</runas></command>
15 <option><authenticate>on</authenticate></option>
16 <command><path>/sbin/mount -o nosuid,nodev /dev/cd0a /CDROM</path></command>
17 </sudoers>
18 <sudoers>
19 <subject><name>def</name><type>posixGroup</type></subject>
20 <option><authenticate>off</authenticate></option>
21 </sudoers>
22 <sudoers>
23 <subject><name>EWLFKFKJKFwe</name><type>ALL</type></subject>
24 <command><path>/sbin/shutdown -r now</path></command>
25 <option><lecture>always</lecture></option>
26 </sudoers>
27 </ipaconfig>
28
29 </ipa>
- Line 2: every IPA policy must start with an <ipa> tag together with an appropriate namespace definition.
- line 3-8: Policy metadata, currently I am not sure if it is a good idea to store the GUID and the last modification time also here or only in the DS. If we do it we must take care to keep them in sync on the server side. On the client side it would be nice to have this information in the policy file, because then the client does not need to store this information at some extra place. The client will need GUID and modification time to see if his copy is still valid or if a newer version is available.
- line 11-27: the configuration data of the policy, we will also have <iparole> and <ipaaction>, but the agreement is that they should not be found together in a single file.
- line 12-17: a sudoers item consistion of
- line 13: one or more <subject>s, if anyone knows a better name to describe a user or a group or a netgroup in a single word please tell me, I would very much like to change it
- line 14-15: one or more <command> and <option>
[edit]
RELAX NG schema for Policy validation
<?xml version="1.0" encoding="utf-8"?>
<grammar ns="http://freeipa.org/xml/rng/sudo/sudoers/1.0"
xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
xmlns:pa="http://freeipa.org/xml/rng/ns/plugable_architecture/1.0">
<a:documentation>Sudo configuration (/etc/sudoers)</a:documentation>
<a:documentation>The following section can be used to register the RNG schema file for the UI</a:documentation>
<a:name>sudo</a:name>
<a:description>Creates configuration items for sudo which will be written to /etc/sudoers</a:description>
<a:author>sbose@redhat.com, based on the work of fcusack@redhat.com</a:author>
<a:xslt>sudoers.xsl</a:xslt>
<a:version>0.5</a:version>
<define name="rng_filename"><value>sudoers.rng</value></define>
<define name="xslt_filename"><value>sudoers.xslt</value></define>
<include href="policy_metadata.rng"/>
<start ns="http://freeipa.org/xml/rng/sudo/sudoers/1.0">
<element name="ipa">
<a:documentation>Doc test.</a:documentation>
<ref name="policy_metadata"/>
<element name="ipaconfig">
<a:documentation>Here the definition for the sudo specific part of the policy starts.</a:documentation>
<oneOrMore>
<element name="sudoers">
<oneOrMore>
<element name="subject">
<element name="name">
<text/>
</element>
<element name="type">
<choice>
<value>posixUser</value>
<value>posixGroup</value>
<value>netgroup</value>
<value>IPAgroup</value>
<value>ALL</value>
</choice>
</element>
</element>
</oneOrMore>
<oneOrMore>
<choice>
<element name="command">
<element name="path">
<text />
</element>
<zeroOrMore>
<element name="args">
<text />
</element>
</zeroOrMore>
<zeroOrMore>
<element name="tag">
<choice>
<value>NOPASSWD</value>
<value>PASSWD</value>
<value>NOEXEC</value>
<value>EXEC</value>
<value>SETENV</value>
<value>NOSETENV</value>
</choice>
</element>
</zeroOrMore>
<!-- XXX actually needs to be user,group,netgroup -->
<zeroOrMore>
<element name="runas">
<data type="string">
<param name="pattern">[A-Za-z0-9_-]{1,16}</param>
</data>
</element>
</zeroOrMore>
</element> <!-- command -->
<element name="option">
<oneOrMore>
<choice>
<!-- flag options -->
<element name="always_set_home" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="authenticate" a:defaultValue="on">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="env_editor" a:defaultValue="on">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="env_reset" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="fqdn" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<!--
this option is ignored by sudo
<element name="ignore_dot" a:defaultValue="on">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
-->
<!-- global option only -->
<element name="ignore_local_sudoers" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="insults" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="log_host" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="log_year" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="long_otp_prompt" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="mail_always" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="mail_badpass"
a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="mail_no_host"
a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="mail_no_perms"
a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="mail_no_user" a:defaultValue="on">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="noexec" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="path_info" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="passprompt_override" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="preserve_groups" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="requiretty" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="root_sudo" a:defaultValue="on">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="rootpw" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="runaspw" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="set_home" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="set_logname" a:defaultValue="on">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="setenv" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="shell_noargs" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="stay_setuid" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="targetpw" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<element name="tty_tickets" a:defaultValue="off">
<choice>
<value>on</value>
<value>off</value>
</choice>
</element>
<!-- integer options -->
<element name="passwd_tries" a:defaultValue="3">
<data type="integer">
<param name="minInclusive">1</param>
<param name="maxInclusive">65535</param>
<!-- ??? -->
</data>
</element>
<!-- integer/boolean options -->
<element name="loglinelen" a:defaultValue="80">
<data type="integer">
<param name="minInclusive">0</param>
<param name="maxInclusive">65535</param>
<!-- ??? -->
</data>
</element>
<element name="passwd_timeout" a:defaultValue="0">
<data type="integer">
<param name="minInclusive">0</param>
<param name="maxInclusive">65535</param>
<!-- ??? -->
</data>
</element>
<element name="timestamp_timeout" a:defaultValue="5">
<data type="integer">
<param name="minInclusive">-1</param>
<param name="maxInclusive">65535</param>
<!-- ??? -->
</data>
</element>
<element name="umask" a:defaultValue="0022">
<data type="string">
<param name="pattern">(0[0-7]{3})</param>
</data>
</element>
<!-- string options -->
<element name="badpass_message" a:defaultValue="Sorry, try again.">
<text />
</element>
<element name="editor" a:defaultValue="/PATH/TO/VI">
<!-- NOTE: absolute path not required -->
<text />
</element>
<element name="mailsub" a:defaultValue="*** SECURITY information for %h ***">
<text />
</element>
<element name="noexec_file" a:defaultValue="/PATH/TO/SUDO_NOEXEC.SO">
<data type="string">
<param name="pattern">/.*</param>
</data>
</element>
<element name="passprompt" a:defaultValue="Password:">
<text />
</element>
<element name="role" a:defaultValue="">
<text />
</element>
<element name="runas_default" a:defaultValue="root">
<data type="string">
<param name="pattern">
[A-Za-z0-9_-]{1,16}</param>
</data>
</element>
<element name="syslog_badpri" a:defaultValue="alert">
<choice>
<value>emerg</value>
<value>alert</value>
<value>crit</value>
<value>err</value>
<value>warning</value>
<value>notice</value>
<value>info</value>
<value>debug</value>
</choice>
</element>
<element name="syslog_goodpri" a:defaultValue="notice">
<choice>
<value>emerg</value>
<value>alert</value>
<value>crit</value>
<value>err</value>
<value>warning</value>
<value>notice</value>
<value>info</value>
<value>debug</value>
</choice>
</element>
<element name="timestampdir" a:defaultValue="/var/db/sudo">
<data type="string">
<param name="pattern">/.*</param>
</data>
</element>
<element name="timestampowner" a:defaultValue="root">
<data type="string">
<param name="pattern">
[A-Za-z0-9_-]{1,16}</param>
</data>
</element>
<element name="type" a:defaultValue="">
<text />
</element>
<!-- string/boolean options -->
<!-- possibly bad option for us -->
<element name="exempt_group" a:defaultValue="off">
<text />
</element>
<element name="lecture" a:defaultValue="once">
<choice>
<value>always</value>
<value>never</value>
<value>once</value>
</choice>
</element>
<element name="lecture_file" a:defaultValue="built-in">
<data type="string">
<param name="pattern">(/.*|built-in)</param>
</data>
</element>
<!-- possibly bad for us -->
<element name="listpw" a:defaultValue="any">
<choice>
<value>all</value>
<value>always</value>
<value>any</value>
<value>never</value>
</choice>
</element>
<element name="logfile" a:defaultValue="off">
<data type="string">
<param name="pattern">(/.*|off)</param>
</data>
</element>
<element name="mailerflags" a:defaultValue="-t">
<text />
</element>
<element name="mailerpath" a:defaultValue="/PATH/TO/SENDMAIL">
<text />
</element>
<element name="syslog" a:defaultValue="authpriv">
<choice>
<value>auth</value>
<value>authpriv</value>
<value>daemon</value>
<value>user</value>
<value>local0</value>
<value>local1</value>
<value>local2</value>
<value>local3</value>
<value>local4</value>
<value>local5</value>
<value>local6</value>
<value>local7</value>
<value>off</value>
</choice>
</element>
<element name="verifypw" a:defaultValue="all">
<choice>
<value>all</value>
<value>always</value>
<value>any</value>
<value>never</value>
</choice>
</element>
<!-- list/boolean options -->
<element name="env_check" a:defaultValue="">
<list>
<oneOrMore>
<data type="string" />
</oneOrMore>
</list>
</element>
<element name="env_delete" a:defaultValue="">
<list>
<oneOrMore>
<data type="string" />
</oneOrMore>
</list>
</element>
<element name="env_keep" a:defaultValue="">
<list>
<oneOrMore>
<data type="string" />
</oneOrMore>
</list>
</element>
</choice>
</oneOrMore>
</element>
</choice>
</oneOrMore>
</element> <!-- sudoers -->
</oneOrMore>
</element> <!-- ipaconfig -->
</element> <!-- ipa -->
</start>
</grammar>
[edit]
Include file for Policy Metadata
1 <?xml version="1.0" encoding="utf-8"?>
2 <grammar xmlns="http://relaxng.org/ns/structure/1.0"
3 datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
4 xmlns:a="http://freeipa.org/xml/rng/ns/annotations/1.0"
5 xmlns:pa="http://freeipa.org/xml/rng/ns/plugable_architecture/1.0">
6
7
8 <define name="policy_metadata">
9 <element name="metadata">
10
11 <a:doc>The metadata information should be generic for all policies. The RelaxNG schema can be found in a separate file (this file :) and can be included by the schema file of a specific policy with the include pattern. With this separation the policy and the metadata schema can be modified independently and the metadata schema can be used by the UI to render a separate page for the metadata of a policy.</a:doc>
12
13 <element name="name">
14 <text/>
15 </element>
16
17 <element name="author" pa:edit="no">
18 <a:doc>should be added automatically, use login information</a:doc>
19 <text/>
20 </element>
21
22 <element name="version" pa:edit="no">
23 <a:doc>should be added automatically</a:doc>
24 <text/>
25 </element>
26
27 <element name="RNGfile" pa:label="Name of the RELAX NG file">
28 <a:doc>should be added automatically from RelaxNG metadata</a:doc>
29 <ref name="rng_filename"/>
30 </element>
31
32 <element name="XSLTfile" pa:label="Name of the XSLT file">
33 <a:doc>should be added automatically from RelaxNG metadata</a:doc>
34 <ref name="xslt_filename"/>
35 </element>
36
37 <optional>
38 <element name="mergeStrategyXML" pa:label="Howto merge with other policies">
39 <choice>
40 <value pa:label="Use only this policy">exclusive</value>
41 <value pa:label="Merge with other policies">merge</value>
42 <value pa:label="Ignore this, if other policies apply">ignore</value>
43 </choice>
44 </element>
45
46 <element name="mergeStrategyLocal" pa:label="Howto merge with local files">
47 <choice>
48 <value pa:label="Use only this policy">exclusive</value>
49 <value pa:label="Merge with local file">merge</value>
50 <value pa:label="Ignore this, if local file exsits">ignore</value>
51 </choice>
52 </element>
53
54 <element name="description" pa:label="Description, what should the policy do and why, maybe a changelog">
55 <text/>
56 </element>
57
58 </optional>
59 </element>
60 </define>
61 </grammar>
[edit]
XSLT for for transformation
1 <?xml version="1.0" encoding="UTF-8"?>
2 <xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 xmlns:xs="http://www.w3.org/2001/XMLSchema"
5 xmlns:md="http://freeipa.org/xsl/metadata/1.0"
6 xmlns:sudoers="http://freeipa.org/xml/rng/sudo/sudoers/1.0">
7
8 <md:output_file name="/etc/sudoers" owner="root" group="root" permission="440"/>
9
10 <xsl:output method="text" indent="no"/>
11 <xsl:strip-space elements="*"/>
12
13 <xsl:template match="/">
14 <xsl:text># IPA generated /etc/sudoers: DO NOT EDIT
</xsl:text>
15 <xsl:apply-templates select="sudoers:ipa"/>
16 </xsl:template>
17
18 <xsl:template match="sudoers:ipa">
19 <xsl:apply-templates>
20 <xsl:with-param name="sudoers:ipaconfig"/>
21 </xsl:apply-templates>
22 </xsl:template>
23
24 <xsl:template match="sudoers:ipaconfig">
25 <xsl:apply-templates>
26 <xsl:with-param name="sudoers:sudoers" select="''"/>
27 </xsl:apply-templates>
28 </xsl:template>
29
30
31 <xsl:template match="sudoers:metadata">
32 </xsl:template>
33
34 <xsl:template match="sudoers:sudoers">
35 <xsl:variable name="name">
36 <xsl:apply-templates select="sudoers:subject">
37 </xsl:apply-templates>
38 </xsl:variable>
39
40 <xsl:apply-templates select="sudoers:command|sudoers:option">
41 <xsl:with-param name="name" select="$name"/>
42 </xsl:apply-templates>
43 </xsl:template>
44
45
46
47 <xsl:template match="sudoers:subject">
48 <xsl:call-template name="format_name">
49 <xsl:with-param name="name" select="sudoers:name"/>
50 <xsl:with-param name="type" select="sudoers:type"/>
51 </xsl:call-template>
52 </xsl:template>
53
54 <xsl:template match="sudoers:option">
55 <xsl:param name="name"/>
56 <xsl:text>Default</xsl:text>
57 <xsl:choose>
58 <xsl:when test="$name = 'ALL'">
59 <xsl:text> </xsl:text>
60 </xsl:when>
61 <xsl:otherwise>
62 <xsl:text>:</xsl:text>
63 <xsl:value-of select="$name"/>
64 <xsl:text> </xsl:text>
65 </xsl:otherwise>
66 </xsl:choose>
67 <xsl:for-each select="*">
68 <xsl:choose>
69 <!-- boolean options -->
70 <xsl:when test="name()='always_set_home' or
71 name()='authenticate' or
72 name()='env_editor' or
73 name()='env_reset' or
74 name()='fqdn' or
75 name()='ignore_dot' or
76 name()='ignore_local_sudoers' or
77 name()='insults' or
78 name()='log_host' or
79 name()='log_year' or
80 name()='long_otp_prompt' or
81 name()='mail_always' or
82 name()='mail_badpass' or
83 name()='mail_no_host' or
84 name()='mail_no_perms' or
85 name()='mail_no_user' or
86 name()='noexec' or
87 name()='path_info' or
88 name()='passprompt_override' or
89 name()='preserve_groups' or
90 name()='requiretty' or
91 name()='root_sudo' or
92 name()='rootpw' or
93 name()='runaspw' or
94 name()='set_home' or
95 name()='set_logname' or
96 name()='setenv' or
97 name()='shell_noargs' or
98 name()='stay_setuid' or
99 name()='targetpw' or
100 name()='tty_tickets'
101 ">
102 <xsl:if test=". = 'off'">
103 <xsl:text>!</xsl:text>
104 </xsl:if>
105 <xsl:value-of select="name()"/>
106 </xsl:when>
107
108 <!-- integer option -->
109 <xsl:when test="name()='passwd_tries'" >
110 <xsl:value-of select="name()"/>
111 <xsl:text>=</xsl:text>
112 <xsl:value-of select="."/>
113 </xsl:when>
114
115 <!-- integer/booleans option, we handle them like integers -->
116 <xsl:when test="name()='loglinelen' or
117 name()='passwd_timeout' or
118 name()='timestamp_timeout' or
119 name()='umask'
120 ">
121 <xsl:value-of select="name()"/>
122 <xsl:text>=</xsl:text>
123 <xsl:value-of select="."/>
124 </xsl:when>
125
126 <!-- string options -->
127 <xsl:when test="name()='badpass_message' or
128 name()='editor' or
129 name()='mailsub' or
130 name()='noexec_file' or
131 name()='passprompt' or
132 name()='role' or
133 name()='runas_default' or
134 name()='syslog_badpri' or
135 name()='syslog_goodpri' or
136 name()='timestampdir' or
137 name()='timestampowner' or
138 name()='type'
139 ">
140 <xsl:value-of select="name()"/>
141 <xsl:text>="</xsl:text>
142 <xsl:value-of select="."/>
143 <xsl:text>"</xsl:text>
144 </xsl:when>
145 <!-- string/boolean options -->
146 <xsl:when test="name()='exempt_group' or
147 name()='lecture' or
148 name()='lecture_file' or
149 name()='listpw' or
150 name()='logfile' or
151 name()='mailerflags' or
152 name()='mailerpath' or
153 name()='mailto' or
154 name()='syslog' or
155 name()='verifypw'
156 ">
157 <xsl:choose>
158 <xsl:when test=".='off'">
159 <xsl:text>!</xsl:text>
160 <xsl:value-of select="name()"/>
161 </xsl:when>
162 <xsl:otherwise>
163 <xsl:value-of select="name()"/>
164 <xsl:text>="</xsl:text>
165 <xsl:value-of select="."/>
166 <xsl:text>"</xsl:text>
167 </xsl:otherwise>
168 </xsl:choose>
169 </xsl:when>
170
171 <!-- list/boolean options -->
172 <xsl:when test="name()='env_check' or
173 name()='env_delete' or
174 name()='env_keep'
175 ">
176 <xsl:choose>
177 <xsl:when test=".='off'">
178 <xsl:text>!</xsl:text>
179 <xsl:value-of select="name()"/>
180 </xsl:when>
181 <xsl:otherwise>
182 <xsl:value-of select="name()"/>
183 <xsl:text>="</xsl:text>
184 <xsl:value-of select="."/>
185 <xsl:text>"</xsl:text>
186 </xsl:otherwise>
187 </xsl:choose>
188 </xsl:when>
189 </xsl:choose>
190 </xsl:for-each>
191 <xsl:text>
</xsl:text>
192 </xsl:template>
193
194 <xsl:template match="sudoers:command">
195 <xsl:param name="name"/>
196 <xsl:variable name="command" select="sudoers:path"/>
197 <xsl:variable name="runas" select="sudoers:runas"/>
198 <xsl:variable name="tag">
199 <xsl:call-template name="format_tag">
200 <xsl:with-param name="tag" select="sudoers:tag"/>
201 </xsl:call-template>
202 </xsl:variable>
203
204 <xsl:value-of select="$name"/>
205 <xsl:text> ALL = </xsl:text>
206 <xsl:if test="$runas != ''">
207 <xsl:text>(</xsl:text>
208 <xsl:value-of select="$runas"/>
209 <xsl:text>) </xsl:text>
210 </xsl:if>
211 <xsl:if test="$tag != ''">
212 <xsl:value-of select="$tag"/>
213 <xsl:text> </xsl:text>
214 </xsl:if>
215 <xsl:value-of select="$command"/>
216 <xsl:text>
</xsl:text>
217 </xsl:template>
218
219 <xsl:template name="format_name">
220 <xsl:param name="name"/>
221 <xsl:param name="type"/>
222
223 <xsl:choose>
224 <xsl:when test="$type = 'ALL'">
225 <xsl:text>ALL</xsl:text>
226 </xsl:when>
227 <xsl:otherwise>
228 <xsl:choose>
229 <xsl:when test="$type = 'netgroup'">
230 <xsl:text>+</xsl:text>
231 </xsl:when>
232 <xsl:when test="$type = 'posixGroup'">
233 <xsl:text>%</xsl:text>
234 </xsl:when>
235 </xsl:choose>
236 <xsl:value-of select="$name"/>
237 </xsl:otherwise>
238 </xsl:choose>
239 </xsl:template>
240
241 <xsl:template name="format_tag">
242 <xsl:param name="tag"/>
243
244 <xsl:if test="$tag != ''">
245 <xsl:value-of select="$tag"/>
246 <xsl:text>:</xsl:text>
247 </xsl:if>
248 </xsl:template>
249 </xsl:stylesheet>
[edit]
Simple client program for validation and transformation using libxml2 and libxslt
worker.c is a simple C program which will
- load an XML
- read the names of the RNG and XSLT file from the file via XPath
- validates the file with the help of the RNG file
- load the XSLT file
- read information about the destination file from the XSLT file
- translate the XML file with the help of the XSLT file


