FreeIPA
banners
Contribute to FreeIPA!

From Free IPA

Contents

Introduction

In the following all necessary files for for the IPA sudo policy are listed and described.

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>

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>

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>

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>

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
Views Article Discussion Edit History
Personal tools:  Log in / create account
Toolbox What links here Related changes Upload file Special pages Printable version