summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEamon Walsh <ewalsh@tycho.nsa.gov>2008-12-03 17:50:36 -0500
committerEamon Walsh <ewalsh@tycho.nsa.gov>2008-12-03 17:50:36 -0500
commite6a37c49a5618ee1dcb27ae6e4b839457bb04eeb (patch)
tree9e9441d8e512eb741beff4886f6d4cac1c7f90fe
Initial commit.
Add mcstrans with modifications by Joe Nall.
-rw-r--r--COPYING340
-rw-r--r--ChangeLog8
-rw-r--r--Makefile16
-rw-r--r--VERSION1
-rw-r--r--conf/README60
-rw-r--r--conf/setrans.conf23
-rw-r--r--conf/setrans.d/ab.conf6
-rw-r--r--conf/setrans.d/eyes-only.conf741
-rw-r--r--conf/setrans.d/pipes.conf11
-rw-r--r--conf/setrans.d/rel.conf746
-rw-r--r--man/Makefile10
-rw-r--r--man/man8/mcs.830
-rw-r--r--mcstrans.spec159
-rw-r--r--src/Makefile44
-rw-r--r--src/README3
-rw-r--r--src/mcstrans.c1395
-rw-r--r--src/mcstrans.h9
-rw-r--r--src/mcstrans.init112
-rw-r--r--src/mcstransd.c609
-rw-r--r--src/mls_level.c164
-rw-r--r--src/mls_level.h10
-rw-r--r--test/ab.test11
-rw-r--r--test/eyes-only-range.test3
-rw-r--r--test/eyes-only.test734
-rw-r--r--test/mixed.test5
-rw-r--r--test/pipes.test6
-rw-r--r--test/rel-range.test4
-rw-r--r--test/rel.test734
-rw-r--r--test/setrans.test51
-rw-r--r--utils/Makefile41
-rwxr-xr-xutils/callgrind-mcstransd5
-rwxr-xr-xutils/mlstrans-test-runner.py53
-rw-r--r--utils/transcon.c30
-rw-r--r--utils/untranscon.c28
-rwxr-xr-xutils/valgrind-mcstransd5
35 files changed, 6207 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..d60c31a
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..743757a
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,8 @@
+0.3.0 2008-06-10
+ * Add inverse bit support
+0.2.1 2007-02-6
+ * Rewrite for Proper MLS Translations
+0.1.8 2005-08-5
+ * Add Chad Hanson Patch for MLS
+0.1.0 2005-08-5
+ * Initial public release.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..63df4a3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,16 @@
+all:
+ $(MAKE) -C src
+ $(MAKE) -C utils
+
+install:
+ $(MAKE) -C src install
+# $(MAKE) -C utils install
+ $(MAKE) -C man install
+
+clean:
+ rm -f *~ \#*
+ $(MAKE) -C src clean
+ $(MAKE) -C utils clean
+ $(MAKE) -C man clean
+
+
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..0d91a54
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.3.0
diff --git a/conf/README b/conf/README
new file mode 100644
index 0000000..cc96dd4
--- /dev/null
+++ b/conf/README
@@ -0,0 +1,60 @@
+# Syntax
+
+# A domain is a self consistent domain of translation (English, German, Paragraph Markings ...)
+Domain=NAME1
+
+# Within a domain are a number of fixed translations
+# format is raw_range=trans_range
+s3:c200.c511=Confidential
+# repeat as required...
+
+# Within a domain are variable translations that are a Base + ModifierGroup + ModifierGroup
+Base=Sensitivity Levels
+# raw_range=name
+s1=Unclassified
+# Aliases have the same name but a different translation.
+# The first one is used to compute translations
+s1=U
+# inverse bits should appear in the base of any level that uses inverse bits
+s2:c200.c511=Restricted
+# repeat as required...
+
+# Modifier Groups should be in the order of appearance in the translated range.
+ModifierGroup=GROUP1
+# Allowed white space can be defined
+Whitespace=- ,/
+# Join defines the character between multiple members of this group
+Join=/
+# A Prefix can be defined per group
+Prefix=Releasable to
+# Inverse categories (releasabilities) should always be set as Default categories in every ModifierGroup
+Default=c200.c511
+# format is raw_categories=name
+# ~ turns off inverse bits
+~c200.c511=EVERYBODY
+
+# Aruba - bit 201
+~c200,~c201=ABW
+~c200,~c201=AA
+# Afghanistan - bit 202
+~c200,~c202=AFG
+~c200,~c202=AF
+# repeat as required...
+
+# Another Modifier Group
+ModifierGroup=GROUP2
+# With different white space
+Whitespace=
+# And different Join
+Join=,
+# A Suffix can be defined per group
+Suffix=Eyes only
+# Default categories need to be consistent
+Default=c200.c511
+
+# New domain
+Domain=NAME2
+
+# any text can be put in a separate file
+Include=PATH
+Include=PATH
diff --git a/conf/setrans.conf b/conf/setrans.conf
new file mode 100644
index 0000000..47d9847
--- /dev/null
+++ b/conf/setrans.conf
@@ -0,0 +1,23 @@
+
+Domain=Test
+
+s0=SystemLow
+s15:c0.c1023=SystemHigh
+s0-s15:c0.c1023=SystemLow-SystemHigh
+
+Base=Sensitivity Levels
+s1=Unclassified
+s1=U
+s2:c200.c511=Restricted
+s2:c200.c511=R
+s3:c200.c511=Confidential
+s3:c200.c511=C
+s4:c200.c511=Secret
+s4:c200.c511=S
+s5:c200.c511=Top Secret
+s5:c200.c511=TS
+
+Include=/etc/selinux/mls/setrans.d/ab.conf
+Include=/etc/selinux/mls/setrans.d/rel.conf
+Include=/etc/selinux/mls/setrans.d/eyes-only.conf
+Include=/etc/selinux/mls/setrans.d/pipes.conf
diff --git a/conf/setrans.d/ab.conf b/conf/setrans.d/ab.conf
new file mode 100644
index 0000000..050e6bd
--- /dev/null
+++ b/conf/setrans.d/ab.conf
@@ -0,0 +1,6 @@
+ModifierGroup=AB
+Default=c200.c511
+
+c0,c1=AB
+c0=A
+c1=B
diff --git a/conf/setrans.d/eyes-only.conf b/conf/setrans.d/eyes-only.conf
new file mode 100644
index 0000000..69c4d4f
--- /dev/null
+++ b/conf/setrans.d/eyes-only.conf
@@ -0,0 +1,741 @@
+ModifierGroup=Inverse Eyes Only
+Whitespace=- ,/
+Join=/
+Suffix=Eyes only
+Default=c200.c511
+
+# Aruba - bit 201
+~c201=ABW
+~c201=AA
+# Afghanistan - bit 202
+~c202=AFG
+~c202=AF
+# Angola - bit 203
+~c203=AGO
+~c203=AO
+# Anguilla - bit 204
+~c204=AIA
+~c204=AV
+# Albania - bit 205
+~c205=ALB
+~c205=AL
+# Andorra - bit 206
+~c206=AND
+~c206=AN
+# Netherlands Antilles - bit 207
+~c207=ANT
+~c207=NT
+# United Arab Emirates - bit 208
+~c208=ARE
+~c208=AE
+# Argentina - bit 209
+~c209=ARG
+~c209=AR
+# Armenia - bit 210
+~c210=ARM
+~c210=AM
+# American Samoa - bit 211
+~c211=ASM
+~c211=AQ
+# Antarctica - bit 212
+~c212=ATA
+~c212=AY
+# French Southern and Antarctic Lands - bit 213
+~c213=ATF
+~c213=FS
+# Antigua and Barbuda - bit 214
+~c214=ATG
+~c214=AC
+# Australia - bit 215
+~c215=AUS
+~c215=AS
+# Austria - bit 216
+~c216=AUT
+~c216=AU
+# Azerbaijan - bit 217
+~c217=AZE
+~c217=AJ
+# Burundi - bit 218
+~c218=BDI
+~c218=BY
+# Belgium - bit 219
+~c219=BEL
+~c219=BE
+# Benin - bit 220
+~c220=BEN
+~c220=BN
+# Burkina Faso - bit 221
+~c221=BFA
+~c221=UV
+# Bangladesh - bit 222
+~c222=BGD
+~c222=BG
+# Bulgaria - bit 223
+~c223=BGR
+~c223=BU
+# Bahrain - bit 224
+~c224=BHR
+~c224=BA
+# Bahamas, The - bit 225
+~c225=BHS
+~c225=BF
+# Bosnia and Herzegovina - bit 226
+~c226=BIH
+~c226=BK
+# Saint Barthelemy - bit 227
+~c227=BLM
+~c227=TB
+# Belarus - bit 228
+~c228=BLR
+~c228=BO
+# Belize - bit 229
+~c229=BLZ
+~c229=BH
+# Bermuda - bit 230
+~c230=BMU
+~c230=BD
+# Bolivia - bit 231
+~c231=BOL
+~c231=BL
+# Brazil - bit 232
+~c232=BRA
+~c232=BR
+# Barbados - bit 233
+~c233=BRB
+~c233=BB
+# Brunei - bit 234
+~c234=BRN
+~c234=BX
+# Bhutan - bit 235
+~c235=BTN
+~c235=BT
+# Bouvet Island - bit 236
+~c236=BVT
+~c236=BV
+# Botswana - bit 237
+~c237=BWA
+~c237=BC
+# Central African Republic - bit 238
+~c238=CAF
+~c238=CT
+# Canada - bit 239
+~c239=CAN
+~c239=CA
+# Cocos (Keeling) Islands - bit 240 part of AUS
+~c240=CCK
+~c240=CK
+# Switzerland - bit 241
+~c241=CHE
+~c241=SZ
+# Chile - bit 242
+~c242=CHL
+~c242=CI
+# China - bit 243
+~c243=CHN
+~c243=CH
+# Cote d'Ivoire - bit 244
+~c244=CIV
+~c244=IV
+# Cameroon - bit 245
+~c245=CMR
+~c245=CM
+# Congo, Democratic Republic of the - bit 246
+~c246=COD
+~c246=CG
+# Congo, Republic of the - bit 247
+~c247=COG
+~c247=CF
+# Cook Islands - bit 248
+~c248=COK
+~c248=CW
+# Colombia - bit 249
+~c249=COL
+~c249=CO
+# Comoros - bit 250
+~c250=COM
+~c250=CN
+# Cape Verde - bit 251
+~c251=CPV
+~c251=CV
+# Costa Rica - bit 252
+~c252=CRI
+~c252=CS
+# Cuba - bit 253
+~c253=CUB
+~c253=CU
+# Christmas Island - bit 254
+~c254=CXR
+~c254=KT
+# Cayman Islands - bit 255
+~c255=CYM
+~c255=CJ
+# Cyprus - bit 256
+~c256=CYP
+~c256=CY
+# Czech Republic - bit 257
+~c257=CZE
+~c257=EZ
+# Germany - bit 258
+~c258=DEU
+~c258=GM
+# Djibouti - bit 259
+~c259=DJI
+~c259=DJ
+# Dominica - bit 260
+~c260=DMA
+~c260=DO
+# Denmark - bit 261
+~c261=DNK
+~c261=DA
+# Dominican Republic - bit 262
+~c262=DOM
+~c262=DR
+# Algeria - bit 263
+~c263=DZA
+~c263=AG
+# Ecuador - bit 264
+~c264=ECU
+~c264=EC
+# Egypt - bit 265
+~c265=EGY
+~c265=EG
+# Eritrea - bit 266
+~c266=ERI
+~c266=ER
+# Western Sahara - bit 267
+~c267=ESH
+~c267=WI
+# Spain - bit 268
+~c268=ESP
+~c268=SP
+# Estonia - bit 269
+~c269=EST
+~c269=EN
+# Ethiopia - bit 270
+~c270=ETH
+~c270=ET
+# Finland - bit 271
+~c271=FIN
+~c271=FI
+# Fiji - bit 272
+~c272=FJI
+~c272=FJ
+# Falkland Islands (Islas Malvinas) - bit 273
+~c273=FLK
+~c273=FK
+# France - bit 274
+~c274=FRA
+~c274=FR
+# Faroe Islands - bit 275
+~c275=FRO
+~c275=FO
+# Micronesia, Federated States of - bit 276
+~c276=FSM
+~c276=FM
+# Gabon - bit 277
+~c277=GAB
+~c277=GB
+# United Kingdom - bit 278
+~c278=GBR
+~c278=UK
+# Georgia - bit 279
+~c279=GEO
+~c279=GG
+# Guernsey - bit 280 part of UK
+~c280=GGY
+~c280=GK
+# Ghana - bit 281
+~c281=GHA
+~c281=GH
+# Gibraltar - bit 282
+~c282=GIB
+~c282=GI
+# Guinea - bit 283
+~c283=GIN
+~c283=GV
+# Guadeloupe - bit 284
+~c284=GLP
+~c284=GP
+# Gambia, The - bit 285
+~c285=GMB
+~c285=GA
+# Guinea-Bissau - bit 286
+~c286=GNB
+~c286=PU
+# Equatorial Guinea - bit 287
+~c287=GNQ
+~c287=EK
+# Greece - bit 288
+~c288=GRC
+~c288=GR
+# Grenada - bit 289
+~c289=GRD
+~c289=GJ
+# Greenland - bit 290
+~c290=GRL
+~c290=GL
+# Guatemala - bit 291
+~c291=GTM
+~c291=GT
+# French Guiana - bit 292
+~c292=GUF
+~c292=FG
+# Guam - bit 293
+~c293=GUM
+~c293=GQ
+# Guyana - bit 294
+~c294=GUY
+~c294=GY
+# Hong Kong - bit 295
+~c295=HKG
+~c295=HK
+# Heard Island and McDonald Islands - bit 296
+~c296=HMD
+~c296=HM
+# Honduras - bit 297
+~c297=HND
+~c297=HO
+# Croatia - bit 298
+~c298=HRV
+~c298=HR
+# Haiti - bit 299
+~c299=HTI
+~c299=HA
+# Hungary - bit 300
+~c300=HUN
+~c300=HU
+# Indonesia - bit 301
+~c301=IDN
+~c301=ID
+# Isle of Man - bit 302 part of UK
+~c302=IMN
+~c302=IM
+# India - bit 303
+~c303=IND
+~c303=IN
+# British Indian Ocean Territory - bit 304
+~c304=IOT
+~c304=IO
+# Ireland - bit 305
+~c305=IRL
+~c305=EI
+# Iran - bit 306
+~c306=IRN
+~c306=IR
+# Iraq - bit 307
+~c307=IRQ
+~c307=IZ
+# Iceland - bit 308
+~c308=ISL
+~c308=IC
+# Israel - bit 309
+~c309=ISR
+~c309=IS
+# Italy - bit 310
+~c310=ITA
+~c310=IT
+# Jamaica - bit 311
+~c311=JAM
+~c311=JM
+# Jersey - bit 312 part of UK
+~c312=JEY
+~c312=JE
+# Jordan - bit 313
+~c313=JOR
+~c313=JO
+# Japan - bit 314
+~c314=JPN
+~c314=JA
+# Kazakhstan - bit 315
+~c315=KAZ
+~c315=KZ
+# Kenya - bit 316
+~c316=KEN
+~c316=KE
+# Kyrgyzstan - bit 317
+~c317=KGZ
+~c317=KG
+# Cambodia - bit 318
+~c318=KHM
+~c318=CB
+# Kiribati - bit 319
+~c319=KIR
+~c319=KR
+# Saint Kitts and Nevis - bit 320
+~c320=KNA
+~c320=SC
+# Korea, South - bit 321
+~c321=KOR
+~c321=ROK
+~c321=KS
+# Kuwait - bit 322
+~c322=KWT
+~c322=KU
+# Laos - bit 323
+~c323=LAO
+~c323=LA
+# Lebanon - bit 324
+~c324=LBN
+~c324=LE
+# Liberia - bit 325
+~c325=LBR
+~c325=LI
+# Libya - bit 326
+~c326=LBY
+~c326=LY
+# Saint Lucia - bit 327
+~c327=LCA
+~c327=ST
+# Liechtenstein - bit 328
+~c328=LIE
+~c328=LS
+# Sri Lanka - bit 329
+~c329=LKA
+~c329=CE
+# Lesotho - bit 330
+~c330=LSO
+~c330=LT
+# Lithuania - bit 331
+~c331=LTU
+~c331=LH
+# Luxembourg - bit 332
+~c332=LUX
+~c332=LU
+# Latvia - bit 333
+~c333=LVA
+~c333=LG
+# Macau - bit 334
+~c334=MAC
+~c334=MC
+# Saint Martin - bit 335
+~c335=MAF
+~c335=RN
+# Morocco - bit 336
+~c336=MAR
+~c336=MO
+# Monaco - bit 337
+~c337=MCO
+~c337=MN
+# Moldova - bit 338
+~c338=MDA
+~c338=MD
+# Madagascar - bit 339
+~c339=MDG
+~c339=MA
+# Maldives - bit 340
+~c340=MDV
+~c340=MV
+# Mexico - bit 341
+~c341=MEX
+~c341=MX
+# Marshall Islands - bit 342
+~c342=MHL
+~c342=RM
+# Macedonia - bit 343 part of FYR
+~c343=MKD
+~c343=MK
+# Mali - bit 344
+~c344=MLI
+~c344=ML
+# Malta - bit 345
+~c345=MLT
+~c345=MT
+# Burma - bit 346
+~c346=MMR
+~c346=BM
+# Montenegro - bit 347
+~c347=MNE
+~c347=MJ
+# Mongolia - bit 348
+~c348=MNG
+~c348=MG
+# Northern Mariana Islands - bit 349
+~c349=MNP
+~c349=CQ
+# Mozambique - bit 350
+~c350=MOZ
+~c350=MZ
+# Mauritania - bit 351
+~c351=MRT
+~c351=MR
+# Montserrat - bit 352
+~c352=MSR
+~c352=MH
+# Martinique - bit 353
+~c353=MTQ
+~c353=MB
+# Mauritius - bit 354
+~c354=MUS
+~c354=MP
+# Malawi - bit 355
+~c355=MWI
+~c355=MI
+# Malaysia - bit 356
+~c356=MYS
+~c356=MY
+# Mayotte - bit 357 part of FRA
+~c357=MYT
+~c357=MF
+# Namibia - bit 358
+~c358=NAM
+~c358=WA
+# New Caledonia - bit 359
+~c359=NCL
+~c359=NC
+# Niger - bit 360
+~c360=NER
+~c360=NG
+# Norfolk Island - bit 361
+~c361=NFK
+~c361=NF
+# Nigeria - bit 362
+~c362=NGA
+~c362=NI
+# Nicaragua - bit 363
+~c363=NIC
+~c363=NU
+# Niue - bit 364
+~c364=NIU
+~c364=NE
+# Netherlands - bit 365
+~c365=NLD
+~c365=NL
+# Norway - bit 366
+~c366=NOR
+~c366=NO
+# Nepal - bit 367
+~c367=NPL
+~c367=NP
+# Nauru - bit 368
+~c368=NRU
+~c368=NR
+# New Zealand - bit 369
+~c369=NZL
+~c369=NZ
+# Oman - bit 370
+~c370=OMN
+~c370=MU
+# Pakistan - bit 371
+~c371=PAK
+~c371=PK
+# Panama - bit 372
+~c372=PAN
+~c372=PM
+# Pitcairn Islands - bit 373
+~c373=PCN
+~c373=PC
+# Peru - bit 374
+~c374=PER
+~c374=PE
+# Philippines - bit 375
+~c375=PHL
+~c375=RP
+# Palau - bit 376
+~c376=PLW
+~c376=PS
+# Papua New Guinea - bit 377
+~c377=PNG
+~c377=PP
+# Poland - bit 378
+~c378=POL
+~c378=PL
+# Puerto Rico - bit 379
+~c379=PRI
+~c379=RQ
+# Korea, North - bit 380
+~c380=PRK
+~c380=KN
+# Portugal - bit 381
+~c381=PRT
+~c381=PO
+# Paraguay - bit 382
+~c382=PRY
+~c382=PA
+# Gaza Strip - bit 383
+~c383=PSE
+~c383=GZ
+# West Bank - bit 383
+~c383=WE
+# French Polynesia - bit 384
+~c384=PYF
+~c384=FP
+# Qatar - bit 385
+~c385=QAT
+~c385=QA
+# Reunion - bit 386
+~c386=REU
+~c386=RE
+# Romania - bit 387
+~c387=ROU
+~c387=RO
+# Russia - bit 388
+~c388=RUS
+~c388=RS
+# Rwanda - bit 389
+~c389=RWA
+~c389=RW
+# Saudi Arabia - bit 390
+~c390=SAU
+~c390=SA
+# Sudan - bit 391
+~c391=SDN
+~c391=SU
+# Senegal - bit 392
+~c392=SEN
+~c392=SG
+# Singapore - bit 393
+~c393=SGP
+~c393=SN
+# South Georgia and the Islands - bit 394
+~c394=SGS
+~c394=SX
+# Saint Helena - bit 395
+~c395=SHN
+~c395=SH
+# Svalbard - bit 396
+~c396=SJM
+~c396=SV
+# Solomon Islands - bit 397
+~c397=SLB
+~c397=BP
+# Sierra Leone - bit 398
+~c398=SLE
+~c398=SL
+# El Salvador - bit 399
+~c399=SLV
+~c399=ES
+# San Marino - bit 400
+~c400=SMR
+~c400=SM
+# Somalia - bit 401
+~c401=SOM
+~c401=SO
+# Saint Pierre and Miquelon - bit 402
+~c402=SPM
+~c402=SB
+# Serbia - bit 403
+~c403=SRB
+~c403=RB
+# Sao Tome and Principe - bit 404
+~c404=STP
+~c404=TP
+# Suriname - bit 405
+~c405=SUR
+~c405=NS
+# Slovakia - bit 406
+~c406=SVK
+~c406=LO
+# Slovenia - bit 407
+~c407=SVN
+~c407=SI
+# Sweden - bit 408
+~c408=SWE
+~c408=SW
+# Swaziland - bit 409
+~c409=SWZ
+~c409=WZ
+# Seychelles - bit 410
+~c410=SYC
+~c410=SE
+# Syria - bit 411
+~c411=SYR
+~c411=SY
+# Turks and Caicos Islands - bit 412
+~c412=TCA
+~c412=TK
+# Chad - bit 413
+~c413=TCD
+~c413=CD
+# Togo - bit 414
+~c414=TGO
+~c414=TO
+# Thailand - bit 415
+~c415=THA
+~c415=TH
+# Tajikistan - bit 416
+~c416=TJK
+~c416=TI
+# Tokelau - bit 417
+~c417=TKL
+~c417=TL
+# Turkmenistan - bit 418
+~c418=TKM
+~c418=TX
+# Timor-Leste - bit 419
+~c419=TLS
+~c419=TT
+# Tonga - bit 420
+~c420=TON
+~c420=TN
+# Trinidad and Tobago - bit 421
+~c421=TTO
+~c421=TD
+# Tunisia - bit 422
+~c422=TUN
+~c422=TS
+# Turkey - bit 423
+~c423=TUR
+~c423=TU
+# Tuvalu - bit 424
+~c424=TUV
+~c424=TV
+# Taiwan - bit 425
+~c425=TWN
+~c425=TW
+# Tanzania - bit 426
+~c426=TZA
+~c426=TZ
+# Uganda - bit 427
+~c427=UGA
+~c427=UG
+# Ukraine - bit 428
+~c428=UKR
+~c428=UP
+# Uruguay - bit 429
+~c429=URY
+~c429=UY
+# United States - bit 430
+~c430=USA
+~c430=US
+# Uzbekistan - bit 431
+~c431=UZB
+~c431=UZ
+# Holy See (Vatican City) - bit 432
+~c432=VAT
+~c432=VT
+# Saint Vincent and the Grenadines - bit 433
+~c433=VCT
+~c433=VC
+# Venezuela - bit 434
+~c434=VEN
+~c434=VE
+# British Virgin Islands - bit 435
+~c435=VGB
+~c435=VI
+# Virgin Islands - bit 436
+~c436=VIR
+~c436=VQ
+# Vietnam - bit 437
+~c437=VNM
+~c437=VM
+# Vanuatu - bit 438
+~c438=VUT
+~c438=NH
+# Wallis and Futuna - bit 439
+~c439=WLF
+~c439=WF
+# Samoa - bit 440
+~c440=WSM
+~c440=WS
+# Yemen - bit 441
+~c441=YEM
+~c441=YM
+# South Africa - bit 442
+~c442=ZAF
+~c442=SF
+# Zambia - bit 443
+~c443=ZMB
+~c443=ZA
+# Zimbabwe - bit 444
+~c444=ZWE
+~c444=ZI
diff --git a/conf/setrans.d/pipes.conf b/conf/setrans.d/pipes.conf
new file mode 100644
index 0000000..dd1a222
--- /dev/null
+++ b/conf/setrans.d/pipes.conf
@@ -0,0 +1,11 @@
+ModifierGroup=Pipes
+Prefix=Handle Via
+Suffix=Pipes Only
+Suffix=Pipes
+Whitespace=,
+Join=,
+
+c101=Plastic
+c102=Iron
+c103=Copper
+c104=Galvanized
diff --git a/conf/setrans.d/rel.conf b/conf/setrans.d/rel.conf
new file mode 100644
index 0000000..b59796f
--- /dev/null
+++ b/conf/setrans.d/rel.conf
@@ -0,0 +1,746 @@
+ModifierGroup=Inverse Releasable To
+Whitespace=- ,/
+Join=/
+Prefix=Releasable to
+Prefix=Rel
+Prefix=Rel to
+Prefix=Releaseable to
+Default=c200.c511
+
+~c200.c511=EVERYBODY
+
+# Aruba - bit 201
+~c200,~c201=ABW
+~c200,~c201=AA
+# Afghanistan - bit 202
+~c200,~c202=AFG
+~c200,~c202=AF
+# Angola - bit 203
+~c200,~c203=AGO
+~c200,~c203=AO
+# Anguilla - bit 204
+~c200,~c204=AIA
+~c200,~c204=AV
+# Albania - bit 205
+~c200,~c205=ALB
+~c200,~c205=AL
+# Andorra - bit 206
+~c200,~c206=AND
+~c200,~c206=AN
+# Netherlands Antilles - bit 207
+~c200,~c207=ANT
+~c200,~c207=NT
+# United Arab Emirates - bit 208
+~c200,~c208=ARE
+~c200,~c208=AE
+# Argentina - bit 209
+~c200,~c209=ARG
+~c200,~c209=AR
+# Armenia - bit 210
+~c200,~c210=ARM
+~c200,~c210=AM
+# American Samoa - bit 211
+~c200,~c211=ASM
+~c200,~c211=AQ
+# Antarctica - bit 212
+~c200,~c212=ATA
+~c200,~c212=AY
+# French Southern and Antarctic Lands - bit 213
+~c200,~c213=ATF
+~c200,~c213=FS
+# Antigua and Barbuda - bit 214
+~c200,~c214=ATG
+~c200,~c214=AC
+# Australia - bit 215
+~c200,~c215=AUS
+~c200,~c215=AS
+# Austria - bit 216
+~c200,~c216=AUT
+~c200,~c216=AU
+# Azerbaijan - bit 217
+~c200,~c217=AZE
+~c200,~c217=AJ
+# Burundi - bit 218
+~c200,~c218=BDI
+~c200,~c218=BY
+# Belgium - bit 219
+~c200,~c219=BEL
+~c200,~c219=BE
+# Benin - bit 220
+~c200,~c220=BEN
+~c200,~c220=BN
+# Burkina Faso - bit 221
+~c200,~c221=BFA
+~c200,~c221=UV
+# Bangladesh - bit 222
+~c200,~c222=BGD
+~c200,~c222=BG
+# Bulgaria - bit 223
+~c200,~c223=BGR
+~c200,~c223=BU
+# Bahrain - bit 224
+~c200,~c224=BHR
+~c200,~c224=BA
+# Bahamas, The - bit 225
+~c200,~c225=BHS
+~c200,~c225=BF
+# Bosnia and Herzegovina - bit 226
+~c200,~c226=BIH
+~c200,~c226=BK
+# Saint Barthelemy - bit 227
+~c200,~c227=BLM
+~c200,~c227=TB
+# Belarus - bit 228
+~c200,~c228=BLR
+~c200,~c228=BO
+# Belize - bit 229
+~c200,~c229=BLZ
+~c200,~c229=BH
+# Bermuda - bit 230
+~c200,~c230=BMU
+~c200,~c230=BD
+# Bolivia - bit 231
+~c200,~c231=BOL
+~c200,~c231=BL
+# Brazil - bit 232
+~c200,~c232=BRA
+~c200,~c232=BR
+# Barbados - bit 233
+~c200,~c233=BRB
+~c200,~c233=BB
+# Brunei - bit 234
+~c200,~c234=BRN
+~c200,~c234=BX
+# Bhutan - bit 235
+~c200,~c235=BTN
+~c200,~c235=BT
+# Bouvet Island - bit 236
+~c200,~c236=BVT
+~c200,~c236=BV
+# Botswana - bit 237
+~c200,~c237=BWA
+~c200,~c237=BC
+# Central African Republic - bit 238
+~c200,~c238=CAF
+~c200,~c238=CT
+# Canada - bit 239
+~c200,~c239=CAN
+~c200,~c239=CA
+# Cocos (Keeling) Islands - bit 240 part of AUS
+~c200,~c240=CCK
+~c200,~c240=CK
+# Switzerland - bit 241
+~c200,~c241=CHE
+~c200,~c241=SZ
+# Chile - bit 242
+~c200,~c242=CHL
+~c200,~c242=CI
+# China - bit 243
+~c200,~c243=CHN
+~c200,~c243=CH
+# Cote d'Ivoire - bit 244
+~c200,~c244=CIV
+~c200,~c244=IV
+# Cameroon - bit 245
+~c200,~c245=CMR
+~c200,~c245=CM
+# Congo, Democratic Republic of the - bit 246
+~c200,~c246=COD
+~c200,~c246=CG
+# Congo, Republic of the - bit 247
+~c200,~c247=COG
+~c200,~c247=CF
+# Cook Islands - bit 248
+~c200,~c248=COK
+~c200,~c248=CW
+# Colombia - bit 249
+~c200,~c249=COL
+~c200,~c249=CO
+# Comoros - bit 250
+~c200,~c250=COM
+~c200,~c250=CN
+# Cape Verde - bit 251
+~c200,~c251=CPV
+~c200,~c251=CV
+# Costa Rica - bit 252
+~c200,~c252=CRI
+~c200,~c252=CS
+# Cuba - bit 253
+~c200,~c253=CUB
+~c200,~c253=CU
+# Christmas Island - bit 254
+~c200,~c254=CXR
+~c200,~c254=KT
+# Cayman Islands - bit 255
+~c200,~c255=CYM
+~c200,~c255=CJ
+# Cyprus - bit 256
+~c200,~c256=CYP
+~c200,~c256=CY
+# Czech Republic - bit 257
+~c200,~c257=CZE
+~c200,~c257=EZ
+# Germany - bit 258
+~c200,~c258=DEU
+~c200,~c258=GM
+# Djibouti - bit 259
+~c200,~c259=DJI
+~c200,~c259=DJ
+# Dominica - bit 260
+~c200,~c260=DMA
+~c200,~c260=DO
+# Denmark - bit 261
+~c200,~c261=DNK
+~c200,~c261=DA
+# Dominican Republic - bit 262
+~c200,~c262=DOM
+~c200,~c262=DR
+# Algeria - bit 263
+~c200,~c263=DZA
+~c200,~c263=AG
+# Ecuador - bit 264
+~c200,~c264=ECU
+~c200,~c264=EC
+# Egypt - bit 265
+~c200,~c265=EGY
+~c200,~c265=EG
+# Eritrea - bit 266
+~c200,~c266=ERI
+~c200,~c266=ER
+# Western Sahara - bit 267
+~c200,~c267=ESH
+~c200,~c267=WI
+# Spain - bit 268
+~c200,~c268=ESP
+~c200,~c268=SP
+# Estonia - bit 269
+~c200,~c269=EST
+~c200,~c269=EN
+# Ethiopia - bit 270
+~c200,~c270=ETH
+~c200,~c270=ET
+# Finland - bit 271
+~c200,~c271=FIN
+~c200,~c271=FI
+# Fiji - bit 272
+~c200,~c272=FJI
+~c200,~c272=FJ
+# Falkland Islands (Islas Malvinas) - bit 273
+~c200,~c273=FLK
+~c200,~c273=FK
+# France - bit 274
+~c200,~c274=FRA
+~c200,~c274=FR
+# Faroe Islands - bit 275
+~c200,~c275=FRO
+~c200,~c275=FO
+# Micronesia, Federated States of - bit 276
+~c200,~c276=FSM
+~c200,~c276=FM
+# Gabon - bit 277
+~c200,~c277=GAB
+~c200,~c277=GB
+# United Kingdom - bit 278
+~c200,~c278=GBR
+~c200,~c278=UK
+# Georgia - bit 279
+~c200,~c279=GEO
+~c200,~c279=GG
+# Guernsey - bit 280 part of UK
+~c200,~c280=GGY
+~c200,~c280=GK
+# Ghana - bit 281
+~c200,~c281=GHA
+~c200,~c281=GH
+# Gibraltar - bit 282
+~c200,~c282=GIB
+~c200,~c282=GI
+# Guinea - bit 283
+~c200,~c283=GIN
+~c200,~c283=GV
+# Guadeloupe - bit 284
+~c200,~c284=GLP
+~c200,~c284=GP
+# Gambia, The - bit 285
+~c200,~c285=GMB
+~c200,~c285=GA
+# Guinea-Bissau - bit 286
+~c200,~c286=GNB
+~c200,~c286=PU
+# Equatorial Guinea - bit 287
+~c200,~c287=GNQ
+~c200,~c287=EK
+# Greece - bit 288
+~c200,~c288=GRC
+~c200,~c288=GR
+# Grenada - bit 289
+~c200,~c289=GRD
+~c200,~c289=GJ
+# Greenland - bit 290
+~c200,~c290=GRL
+~c200,~c290=GL
+# Guatemala - bit 291
+~c200,~c291=GTM
+~c200,~c291=GT
+# French Guiana - bit 292
+~c200,~c292=GUF
+~c200,~c292=FG
+# Guam - bit 293
+~c200,~c293=GUM
+~c200,~c293=GQ
+# Guyana - bit 294
+~c200,~c294=GUY
+~c200,~c294=GY
+# Hong Kong - bit 295
+~c200,~c295=HKG
+~c200,~c295=HK
+# Heard Island and McDonald Islands - bit 296
+~c200,~c296=HMD
+~c200,~c296=HM
+# Honduras - bit 297
+~c200,~c297=HND
+~c200,~c297=HO
+# Croatia - bit 298
+~c200,~c298=HRV
+~c200,~c298=HR
+# Haiti - bit 299
+~c200,~c299=HTI
+~c200,~c299=HA
+# Hungary - bit 300
+~c200,~c300=HUN
+~c200,~c300=HU
+# Indonesia - bit 301
+~c200,~c301=IDN
+~c200,~c301=ID
+# Isle of Man - bit 302 part of UK
+~c200,~c302=IMN
+~c200,~c302=IM
+# India - bit 303
+~c200,~c303=IND
+~c200,~c303=IN
+# British Indian Ocean Territory - bit 304
+~c200,~c304=IOT
+~c200,~c304=IO
+# Ireland - bit 305
+~c200,~c305=IRL
+~c200,~c305=EI
+# Iran - bit 306
+~c200,~c306=IRN
+~c200,~c306=IR
+# Iraq - bit 307
+~c200,~c307=IRQ
+~c200,~c307=IZ
+# Iceland - bit 308
+~c200,~c308=ISL
+~c200,~c308=IC
+# Israel - bit 309
+~c200,~c309=ISR
+~c200,~c309=IS
+# Italy - bit 310
+~c200,~c310=ITA
+~c200,~c310=IT
+# Jamaica - bit 311
+~c200,~c311=JAM
+~c200,~c311=JM
+# Jersey - bit 312 part of UK
+~c200,~c312=JEY
+~c200,~c312=JE
+# Jordan - bit 313
+~c200,~c313=JOR
+~c200,~c313=JO
+# Japan - bit 314
+~c200,~c314=JPN
+~c200,~c314=JA
+# Kazakhstan - bit 315
+~c200,~c315=KAZ
+~c200,~c315=KZ
+# Kenya - bit 316
+~c200,~c316=KEN
+~c200,~c316=KE
+# Kyrgyzstan - bit 317
+~c200,~c317=KGZ
+~c200,~c317=KG
+# Cambodia - bit 318
+~c200,~c318=KHM
+~c200,~c318=CB
+# Kiribati - bit 319
+~c200,~c319=KIR
+~c200,~c319=KR
+# Saint Kitts and Nevis - bit 320
+~c200,~c320=KNA
+~c200,~c320=SC
+# Korea, South - bit 321
+~c200,~c321=KOR
+~c200,~c321=ROK
+~c200,~c321=KS
+# Kuwait - bit 322
+~c200,~c322=KWT
+~c200,~c322=KU
+# Laos - bit 323
+~c200,~c323=LAO
+~c200,~c323=LA
+# Lebanon - bit 324
+~c200,~c324=LBN
+~c200,~c324=LE
+# Liberia - bit 325
+~c200,~c325=LBR
+~c200,~c325=LI
+# Libya - bit 326
+~c200,~c326=LBY
+~c200,~c326=LY
+# Saint Lucia - bit 327
+~c200,~c327=LCA
+~c200,~c327=ST
+# Liechtenstein - bit 328
+~c200,~c328=LIE
+~c200,~c328=LS
+# Sri Lanka - bit 329
+~c200,~c329=LKA
+~c200,~c329=CE
+# Lesotho - bit 330
+~c200,~c330=LSO
+~c200,~c330=LT
+# Lithuania - bit 331
+~c200,~c331=LTU
+~c200,~c331=LH
+# Luxembourg - bit 332
+~c200,~c332=LUX
+~c200,~c332=LU
+# Latvia - bit 333
+~c200,~c333=LVA
+~c200,~c333=LG
+# Macau - bit 334
+~c200,~c334=MAC
+~c200,~c334=MC
+# Saint Martin - bit 335
+~c200,~c335=MAF
+~c200,~c335=RN
+# Morocco - bit 336
+~c200,~c336=MAR
+~c200,~c336=MO
+# Monaco - bit 337
+~c200,~c337=MCO
+~c200,~c337=MN
+# Moldova - bit 338
+~c200,~c338=MDA
+~c200,~c338=MD
+# Madagascar - bit 339
+~c200,~c339=MDG
+~c200,~c339=MA
+# Maldives - bit 340
+~c200,~c340=MDV
+~c200,~c340=MV
+# Mexico - bit 341
+~c200,~c341=MEX
+~c200,~c341=MX
+# Marshall Islands - bit 342
+~c200,~c342=MHL
+~c200,~c342=RM
+# Macedonia - bit 343 part of FYR
+~c200,~c343=MKD
+~c200,~c343=MK
+# Mali - bit 344
+~c200,~c344=MLI
+~c200,~c344=ML
+# Malta - bit 345
+~c200,~c345=MLT
+~c200,~c345=MT
+# Burma - bit 346
+~c200,~c346=MMR
+~c200,~c346=BM
+# Montenegro - bit 347
+~c200,~c347=MNE
+~c200,~c347=MJ
+# Mongolia - bit 348
+~c200,~c348=MNG
+~c200,~c348=MG
+# Northern Mariana Islands - bit 349
+~c200,~c349=MNP
+~c200,~c349=CQ
+# Mozambique - bit 350
+~c200,~c350=MOZ
+~c200,~c350=MZ
+# Mauritania - bit 351
+~c200,~c351=MRT
+~c200,~c351=MR
+# Montserrat - bit 352
+~c200,~c352=MSR
+~c200,~c352=MH
+# Martinique - bit 353
+~c200,~c353=MTQ
+~c200,~c353=MB
+# Mauritius - bit 354
+~c200,~c354=MUS
+~c200,~c354=MP
+# Malawi - bit 355
+~c200,~c355=MWI
+~c200,~c355=MI
+# Malaysia - bit 356
+~c200,~c356=MYS
+~c200,~c356=MY
+# Mayotte - bit 357 part of FRA
+~c200,~c357=MYT
+~c200,~c357=MF
+# Namibia - bit 358
+~c200,~c358=NAM
+~c200,~c358=WA
+# New Caledonia - bit 359
+~c200,~c359=NCL
+~c200,~c359=NC
+# Niger - bit 360
+~c200,~c360=NER
+~c200,~c360=NG
+# Norfolk Island - bit 361
+~c200,~c361=NFK
+~c200,~c361=NF
+# Nigeria - bit 362
+~c200,~c362=NGA
+~c200,~c362=NI
+# Nicaragua - bit 363
+~c200,~c363=NIC
+~c200,~c363=NU
+# Niue - bit 364
+~c200,~c364=NIU
+~c200,~c364=NE
+# Netherlands - bit 365
+~c200,~c365=NLD
+~c200,~c365=NL
+# Norway - bit 366
+~c200,~c366=NOR
+~c200,~c366=NO
+# Nepal - bit 367
+~c200,~c367=NPL
+~c200,~c367=NP
+# Nauru - bit 368
+~c200,~c368=NRU
+~c200,~c368=NR
+# New Zealand - bit 369
+~c200,~c369=NZL
+~c200,~c369=NZ
+# Oman - bit 370
+~c200,~c370=OMN
+~c200,~c370=MU
+# Pakistan - bit 371
+~c200,~c371=PAK
+~c200,~c371=PK
+# Panama - bit 372
+~c200,~c372=PAN
+~c200,~c372=PM
+# Pitcairn Islands - bit 373
+~c200,~c373=PCN
+~c200,~c373=PC
+# Peru - bit 374
+~c200,~c374=PER
+~c200,~c374=PE
+# Philippines - bit 375
+~c200,~c375=PHL
+~c200,~c375=RP
+# Palau - bit 376
+~c200,~c376=PLW
+~c200,~c376=PS
+# Papua New Guinea - bit 377
+~c200,~c377=PNG
+~c200,~c377=PP
+# Poland - bit 378
+~c200,~c378=POL
+~c200,~c378=PL
+# Puerto Rico - bit 379
+~c200,~c379=PRI
+~c200,~c379=RQ
+# Korea, North - bit 380
+~c200,~c380=PRK
+~c200,~c380=KN
+# Portugal - bit 381
+~c200,~c381=PRT
+~c200,~c381=PO
+# Paraguay - bit 382
+~c200,~c382=PRY
+~c200,~c382=PA
+# Gaza Strip - bit 383
+~c200,~c383=PSE
+~c200,~c383=GZ
+# West Bank - bit 383
+~c200,~c383=WE
+# French Polynesia - bit 384
+~c200,~c384=PYF
+~c200,~c384=FP
+# Qatar - bit 385
+~c200,~c385=QAT
+~c200,~c385=QA
+# Reunion - bit 386
+~c200,~c386=REU
+~c200,~c386=RE
+# Romania - bit 387
+~c200,~c387=ROU
+~c200,~c387=RO
+# Russia - bit 388
+~c200,~c388=RUS
+~c200,~c388=RS
+# Rwanda - bit 389
+~c200,~c389=RWA
+~c200,~c389=RW
+# Saudi Arabia - bit 390
+~c200,~c390=SAU
+~c200,~c390=SA
+# Sudan - bit 391
+~c200,~c391=SDN
+~c200,~c391=SU
+# Senegal - bit 392
+~c200,~c392=SEN
+~c200,~c392=SG
+# Singapore - bit 393
+~c200,~c393=SGP
+~c200,~c393=SN
+# South Georgia and the Islands - bit 394
+~c200,~c394=SGS
+~c200,~c394=SX
+# Saint Helena - bit 395
+~c200,~c395=SHN
+~c200,~c395=SH
+# Svalbard - bit 396
+~c200,~c396=SJM
+~c200,~c396=SV
+# Solomon Islands - bit 397
+~c200,~c397=SLB
+~c200,~c397=BP
+# Sierra Leone - bit 398
+~c200,~c398=SLE
+~c200,~c398=SL
+# El Salvador - bit 399
+~c200,~c399=SLV
+~c200,~c399=ES
+# San Marino - bit 400
+~c200,~c400=SMR
+~c200,~c400=SM
+# Somalia - bit 401
+~c200,~c401=SOM
+~c200,~c401=SO
+# Saint Pierre and Miquelon - bit 402
+~c200,~c402=SPM
+~c200,~c402=SB
+# Serbia - bit 403
+~c200,~c403=SRB
+~c200,~c403=RB
+# Sao Tome and Principe - bit 404
+~c200,~c404=STP
+~c200,~c404=TP
+# Suriname - bit 405
+~c200,~c405=SUR
+~c200,~c405=NS
+# Slovakia - bit 406
+~c200,~c406=SVK
+~c200,~c406=LO
+# Slovenia - bit 407
+~c200,~c407=SVN
+~c200,~c407=SI
+# Sweden - bit 408
+~c200,~c408=SWE
+~c200,~c408=SW
+# Swaziland - bit 409
+~c200,~c409=SWZ
+~c200,~c409=WZ
+# Seychelles - bit 410
+~c200,~c410=SYC
+~c200,~c410=SE
+# Syria - bit 411
+~c200,~c411=SYR
+~c200,~c411=SY
+# Turks and Caicos Islands - bit 412
+~c200,~c412=TCA
+~c200,~c412=TK
+# Chad - bit 413
+~c200,~c413=TCD
+~c200,~c413=CD
+# Togo - bit 414
+~c200,~c414=TGO
+~c200,~c414=TO
+# Thailand - bit 415
+~c200,~c415=THA
+~c200,~c415=TH
+# Tajikistan - bit 416
+~c200,~c416=TJK
+~c200,~c416=TI
+# Tokelau - bit 417
+~c200,~c417=TKL
+~c200,~c417=TL
+# Turkmenistan - bit 418
+~c200,~c418=TKM
+~c200,~c418=TX
+# Timor-Leste - bit 419
+~c200,~c419=TLS
+~c200,~c419=TT
+# Tonga - bit 420
+~c200,~c420=TON
+~c200,~c420=TN
+# Trinidad and Tobago - bit 421
+~c200,~c421=TTO
+~c200,~c421=TD
+# Tunisia - bit 422
+~c200,~c422=TUN
+~c200,~c422=TS
+# Turkey - bit 423
+~c200,~c423=TUR
+~c200,~c423=TU
+# Tuvalu - bit 424
+~c200,~c424=TUV
+~c200,~c424=TV
+# Taiwan - bit 425
+~c200,~c425=TWN
+~c200,~c425=TW
+# Tanzania - bit 426
+~c200,~c426=TZA
+~c200,~c426=TZ
+# Uganda - bit 427
+~c200,~c427=UGA
+~c200,~c427=UG
+# Ukraine - bit 428
+~c200,~c428=UKR
+~c200,~c428=UP
+# Uruguay - bit 429
+~c200,~c429=URY
+~c200,~c429=UY
+# United States - bit 430
+~c200,~c430=USA
+~c200,~c430=US
+# Uzbekistan - bit 431
+~c200,~c431=UZB
+~c200,~c431=UZ
+# Holy See (Vatican City) - bit 432
+~c200,~c432=VAT
+~c200,~c432=VT
+# Saint Vincent and the Grenadines - bit 433
+~c200,~c433=VCT
+~c200,~c433=VC
+# Venezuela - bit 434
+~c200,~c434=VEN
+~c200,~c434=VE
+# British Virgin Islands - bit 435
+~c200,~c435=VGB
+~c200,~c435=VI
+# Virgin Islands - bit 436
+~c200,~c436=VIR
+~c200,~c436=VQ
+# Vietnam - bit 437
+~c200,~c437=VNM
+~c200,~c437=VM
+# Vanuatu - bit 438
+~c200,~c438=VUT
+~c200,~c438=NH
+# Wallis and Futuna - bit 439
+~c200,~c439=WLF
+~c200,~c439=WF
+# Samoa - bit 440
+~c200,~c440=WSM
+~c200,~c440=WS
+# Yemen - bit 441
+~c200,~c441=YEM
+~c200,~c441=YM
+# South Africa - bit 442
+~c200,~c442=ZAF
+~c200,~c442=SF
+# Zambia - bit 443
+~c200,~c443=ZMB
+~c200,~c443=ZA
+# Zimbabwe - bit 444
+~c200,~c444=ZWE
+~c200,~c444=ZI
diff --git a/man/Makefile b/man/Makefile
new file mode 100644
index 0000000..f07ec96
--- /dev/null
+++ b/man/Makefile
@@ -0,0 +1,10 @@
+# Installation directories.
+MAN8DIR ?= $(DESTDIR)/usr/share/man/man8
+
+install:
+ mkdir -p $(MAN8DIR)
+ install -m 644 man8/*.8 $(MAN8DIR)
+
+clean:
+ -rm -f *~ \#*
+ -rm -f man8/*~ man8/\#*
diff --git a/man/man8/mcs.8 b/man/man8/mcs.8
new file mode 100644
index 0000000..6954e0c
--- /dev/null
+++ b/man/man8/mcs.8
@@ -0,0 +1,30 @@
+.TH "mcs" "8" "8 Sep 2005" "dwalsh@redhat.com" "mcs documentation"
+
+.SH "NAME"
+mcs \- Multi-Category System
+
+.SH "DESCRIPTION"
+MCS (Multiple Category System) allows users to label files on their
+system within administrator defined categories. It then uses SELinux
+Mandatory Access Control to protect those files. MCS is a discretionary
+model to allow users to mark their data with additional tags that further
+restrict access. The only mandatory aspect is authorizing users for
+categories by defining their clearance in policy. However, MCS is similar
+to MLS and exercises the same code paths and share the same support
+infrastructure. They just differ in their specific configuration.
+
+
+The
+.I /etc/selinux/{SELINUXTYPE}/setrans.conf configuration file translates the labels on disk to human
+readable form. Administrators can define any labels they want in this file.
+Certain applications like printing and auditing will use these labels to
+identify the files. By setting a category on a file you will prevent
+other applications/services from having access to the files.
+.p
+Examples of file lables would be PatientRecord, CompanyConfidential etc.
+
+.SH "SEE ALSO"
+selinux(8), chcon(1)
+
+.SH FILES
+/etc/selinux/{SELINUXTYPE}/setrans.conf
diff --git a/mcstrans.spec b/mcstrans.spec
new file mode 100644
index 0000000..cbf5837
--- /dev/null
+++ b/mcstrans.spec
@@ -0,0 +1,159 @@
+Summary: SELinux Translation Daemon
+Name: mcstrans
+Version: 0.3.0
+Release: 1%{?dist}
+License: GPL
+Group: System Environment/Daemons
+Source: http://fedora.redhat.com/projects/%{name}-%{version}.tgz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+BuildRequires: libselinux-devel >= 1.30.3-1
+BuildRequires: libcap-devel pcre-devel libsepol-devel libsepol-static
+Requires: pcre
+Requires(pre): /sbin/chkconfig /sbin/service
+Requires(post):/sbin/chkconfig /sbin/service
+Provides: setransd
+Obsoletes: libsetrans
+
+%description
+Security-enhanced Linux is a feature of the Linux® kernel and a number
+of utilities with enhanced security functionality designed to add
+mandatory access controls to Linux. The Security-enhanced Linux
+kernel contains new architectural components originally developed to
+improve the security of the Flask operating system. These
+architectural components provide general support for the enforcement
+of many kinds of mandatory access control policies, including those
+based on the concepts of Type Enforcement®, Role-based Access
+Control, and Multi-level Security.
+
+mcstrans provides an translation daemon to translate SELinux categories
+from internal representations to user defined representation.
+
+%prep
+%setup -q
+
+%build
+make clean
+make CFLAGS="-g %{optflags}"
+
+%install
+rm -rf %{buildroot}
+mkdir -p %{buildroot}/%{_lib}
+mkdir -p %{buildroot}/%{_libdir}
+make DESTDIR="%{buildroot}" LIBDIR="%{buildroot}%{_libdir}" SHLIBDIR="%{buildroot}/%{_lib}" install
+rm -f %{buildroot}%{_sbindir}/*
+rm -f %{buildroot}%{_libdir}/*.a
+
+%clean
+rm -rf %{buildroot}
+
+%post
+chkconfig --add mcstrans
+if [ -f /var/lock/subsys/mcstransd ]; then
+ mv /var/lock/subsys/mcstransd /var/lock/subsys/mcstrans
+fi
+
+%preun
+if [ $1 -eq 0 ]; then
+ service mcstrans stop > /dev/null 2>&1
+ chkconfig --del mcstrans
+fi
+
+%postun
+if [ $1 -ge 1 ]; then
+ service mcstrans condrestart > /dev/null 2>&1 || :
+fi
+
+%files
+%defattr(-,root,root,0755)
+%{_mandir}/man8/mcs.8.gz
+/sbin/mcstransd
+%{_sysconfdir}/rc.d/init.d/mcstrans
+
+%changelog
+* Wed May 7 2008 Dan Walsh <dwalsh@redhat.com> 0.2.11-1
+- More fixes from Jim Meyering
+
+* Tue May 6 2008 Dan Walsh <dwalsh@redhat.com> 0.2.10-1
+- More error checking on failed strdup
+
+* Tue May 6 2008 Dan Walsh <dwalsh@redhat.com> 0.2.9-1
+- Start mcstrans before netlabel
+
+* Mon Apr 14 2008 Dan Walsh <dwalsh@redhat.com> 0.2.8-1
+- Fix error handling
+
+* Tue Feb 12 2008 Dan Walsh <dwalsh@redhat.com> 0.2.7-2
+- Rebuild for gcc 4.3
+
+* Mon Oct 30 2007 Steve Conklin <sconklin@redhat.com> - 0.2.7-1
+- Folded current patches into tarball
+
+* Thu Oct 25 2007 Steve Conklin <sconklin@redhat.com> - 0.2.6-3
+- Fixed a compile problem with max_categories
+
+* Thu Oct 25 2007 Steve Conklin <sconklin@redhat.com> - 0.2.6-2
+- Fixed some init script errors
+
+* Thu Sep 13 2007 Dan Walsh <dwalsh@redhat.com> 0.2.6-1
+- Check for max_categories and error out
+
+* Thu Mar 1 2007 Dan Walsh <dwalsh@redhat.com> 0.2.5-1
+- Fix case where s0=""
+
+* Mon Feb 26 2007 Dan Walsh <dwalsh@redhat.com> 0.2.4-1
+- Translate range if fully specified correctly
+
+* Mon Feb 12 2007 Dan Walsh <dwalsh@redhat.com> 0.2.3-1
+- Additional fix to handle ssh root/sysadm_r/s0:c1,c2
+Resolves: #224637
+
+* Mon Feb 5 2007 Dan Walsh <dwalsh@redhat.com> 0.2.1-1
+- Rewrite to handle MLS properly
+Resolves: #225355
+
+* Mon Jan 29 2007 Dan Walsh <dwalsh@redhat.com> 0.1.10-2
+- Cleanup memory when complete
+
+* Mon Dec 4 2006 Dan Walsh <dwalsh@redhat.com> 0.1.10-1
+- Fix Memory Leak
+Resolves: #218173
+
+* Thu Sep 21 2006 Dan Walsh <dwalsh@redhat.com> 0.1.9-1
+- Add -pie
+- Fix compiler warnings
+- Fix Memory Leak
+Resolves: #218173
+
+* Wed Sep 13 2006 Peter Jones <pjones@redhat.com> - 0.1.8-3
+- Fix subsys locking in init script
+
+* Wed Aug 23 2006 Dan Walsh <dwalsh@redhat.com> 0.1.8-1
+- Only allow one version to run
+
+* Wed Jul 12 2006 Jesse Keating <jkeating@redhat.com> - sh: line 0: fg: no job control
+- rebuild
+
+* Mon Jun 19 2006 Dan Walsh <dwalsh@redhat.com> 0.1.7-1
+- Apply sgrubb patch to only call getpeercon on translations
+
+* Tue Jun 6 2006 Dan Walsh <dwalsh@redhat.com> 0.1.6-1
+- Exit gracefully when selinux is not enabled
+
+* Mon May 15 2006 Dan Walsh <dwalsh@redhat.com> 0.1.5-1
+- Fix sighup handling
+
+* Mon May 15 2006 Dan Walsh <dwalsh@redhat.com> 0.1.4-1
+- Add patch from sgrubb
+- Fix 64 bit size problems
+- Increase the open file limit
+- Make sure maximum size is not exceeded
+
+* Fri May 12 2006 Dan Walsh <dwalsh@redhat.com> 0.1.3-1
+- Move initscripts to /etc/rc.d/init.d
+
+* Thu May 11 2006 Dan Walsh <dwalsh@redhat.com> 0.1.2-1
+- Drop Privs
+
+* Mon May 8 2006 Dan Walsh <dwalsh@redhat.com> 0.1.1-1
+- Initial Version
+- This daemon reuses the code from libsetrans
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..4b034db
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,44 @@
+ARCH = $(shell uname -i)
+ifeq "$(ARCH)" "x86_64"
+ # In case of 64 bit system, use these lines
+ LIBDIR=/usr/lib64
+else
+ifeq "$(ARCH)" "i686"
+ # In case of 32 bit system, use these lines
+ LIBDIR=/usr/lib
+else
+ifeq "$(ARCH)" "i386"
+ # In case of 32 bit system, use these lines
+ LIBDIR=/usr/lib
+endif
+endif
+endif
+# Installation directories.
+PREFIX ?= $(DESTDIR)/usr
+SBINDIR ?= $(DESTDIR)/sbin
+INITDIR ?= $(DESTDIR)/etc/rc.d/init.d
+
+PROG_SRC=mcstrans.c mcstransd.c mls_level.c
+PROG_OBJS= $(patsubst %.c,%.o,$(PROG_SRC))
+PROG=mcstransd
+INITSCRIPT=mcstrans
+CFLAGS ?= -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute
+override CFLAGS += -I../include -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64
+
+all: $(PROG)
+
+$(PROG): $(PROG_OBJS)
+ $(CC) $(LDFLAGS) -pie -o $@ $^ -lselinux -lcap -lpcre $(LIBDIR)/libsepol.a
+
+%.o: %.c
+ $(CC) $(CFLAGS) -fPIE -c -o $@ $<
+
+install: all
+ test -d $(SBINDIR) || install -m 755 -d $(SBINDIR)
+ install -m 755 $(PROG) $(SBINDIR)
+ test -d $(INITDIR) || install -m 755 -d $(INITDIR)
+ install -m 755 $(INITSCRIPT).init $(INITDIR)/$(INITSCRIPT)
+
+clean:
+ -rm -f $(OBJS) $(LOBJS) $(TARGET) $(PROG) $(PROG_OBJS) *~ \#*
+
diff --git a/src/README b/src/README
new file mode 100644
index 0000000..174314a
--- /dev/null
+++ b/src/README
@@ -0,0 +1,3 @@
+To rebuild with debugging support:
+make clean && env CFLAGS="-Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -DDEBUG -g" LDFLAGS="-g" make
+
diff --git a/src/mcstrans.c b/src/mcstrans.c
new file mode 100644
index 0000000..45ead9b
--- /dev/null
+++ b/src/mcstrans.c
@@ -0,0 +1,1395 @@
+
+/* Copyright (c) 2008 Nall Design Works
+ Copyright 2006 Trusted Computer Solutions, Inc. */
+
+/*
+ Exported Interface
+
+ int init_translations(void);
+ void finish_context_translations(void);
+ int trans_context(const security_context_t, security_context_t *);
+ int untrans_context(const security_context_t, security_context_t *);
+
+*/
+
+#include <math.h>
+#include <values.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <ctype.h>
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+#include <syslog.h>
+#include <errno.h>
+#include <pcre.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/time.h>
+
+
+#include "mls_level.h"
+#include "mcstrans.h"
+
+#define N_BUCKETS 101
+#define OVECCOUNT (512*3)
+
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#define log_error(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+
+#ifdef DEBUG
+#define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+#else
+#define log_debug(fmt, ...) ;
+#endif
+
+static unsigned int maxbit=0;
+
+int
+ebitmap_and(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) {
+ unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2));
+ ebitmap_init(dst);
+ for (i=0; i < length; i++) {
+ if (ebitmap_get_bit(e1, i) && ebitmap_get_bit(e2, i)) {
+ int rc = ebitmap_set_bit(dst, i, 1);
+ if (rc < 0)
+ return rc;
+ }
+ }
+ return 0;
+}
+
+int
+ebitmap_xor(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) {
+ unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2));
+ ebitmap_init(dst);
+ for (i=0; i < length; i++) {
+ int val = ebitmap_get_bit(e1, i) ^ ebitmap_get_bit(e2, i);
+ int rc = ebitmap_set_bit(dst, i, val);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+int
+ebitmap_not(ebitmap_t *dst, ebitmap_t *e1) {
+ unsigned int i;
+ ebitmap_init(dst);
+ for (i=0; i < maxbit; i++) {
+ int val = ebitmap_get_bit(e1, i);
+ int rc = ebitmap_set_bit(dst, i, !val);
+ if (rc < 0)
+ return rc;
+ }
+ return 0;
+}
+
+int
+ebitmap_andnot(ebitmap_t *dst, ebitmap_t *e1, ebitmap_t *e2) {
+ ebitmap_t e3;
+ ebitmap_init(dst);
+ int rc = ebitmap_not(&e3, e2);
+ if (rc < 0)
+ return rc;
+ rc = ebitmap_and(dst, e1, &e3);
+ ebitmap_destroy(&e3);
+ if (rc < 0)
+ return rc;
+ return 0;
+}
+
+int
+ebitmap_cardinality(ebitmap_t *e1) {
+ unsigned int i, count = 0;
+ for (i=0; i <= ebitmap_length(e1); i++)
+ if (ebitmap_get_bit(e1, i))
+ count++;
+ return count;
+}
+
+char *
+ebitmap_to_string(ebitmap_t *e, char *buffer) {
+ unsigned int i, level = 0;
+ ebitmap_node_t *cnode;
+
+ char *p = buffer;
+ *p = 0;
+
+ ebitmap_for_each_bit(e, cnode, i) {
+ if (ebitmap_node_get_bit(cnode, i)) {
+ if (level) {
+ level++;
+ continue;
+ }
+
+ if (p != buffer)
+ *p++ = ',';
+ p += sprintf(p, "c%d", i);
+ level++;
+ } else {
+ if (level > 1) {
+ if (level > 2)
+ *p++ = '.';
+ else
+ *p++ = ',';
+
+ p += sprintf(p, "c%d", i-1);
+ }
+ level = 0;
+ }
+ }
+ /* Handle case where last category is the end of level */
+ if (level > 1) {
+ if (level > 2)
+ *p++ = '.';
+ else
+ *p++ = ',';
+
+ p += sprintf(p, "c%d", i-1);
+ }
+
+ return buffer;
+}
+
+int
+hamming_distance(ebitmap_t * e1, ebitmap_t * e2) {
+ if (ebitmap_cmp(e1, e2))
+ return 0;
+ ebitmap_t tmp;
+ int rc = ebitmap_xor(&tmp, e1, e2);
+ if (rc < 0)
+ abort();
+ int distance = ebitmap_cardinality(&tmp);
+ ebitmap_destroy(&tmp);
+ return distance;
+}
+
+/* Define data structures */
+typedef struct context_map {
+ char *raw;
+ char *trans;
+} context_map_t;
+
+typedef struct context_map_node {
+ char *key;
+ context_map_t *map;
+ struct context_map_node *next;
+} context_map_node_t;
+
+typedef struct affix {
+ char *text;
+ struct affix *next;
+} affix_t;
+
+typedef struct word {
+ char *text;
+ ebitmap_t cat;
+ ebitmap_t normal;
+ ebitmap_t inverse;
+ struct word *next;
+} word_t;
+
+typedef struct word_group {
+ char *name;
+ char *whitespace;
+ char *join;
+
+ affix_t *prefixes;
+ affix_t *suffixes;
+ word_t *words;
+
+ pcre *prefix_regexp;
+ pcre *word_regexp;
+ pcre *suffix_regexp;
+
+ ebitmap_t def;
+
+ word_t **sword;
+ int sword_len;
+
+ struct word_group *next;
+} word_group_t;
+
+typedef struct base_classification {
+ char *trans;
+ mls_level_t *level;
+ struct base_classification *next;
+} base_classification_t;
+
+typedef struct domain {
+ char *name;
+
+ context_map_node_t *raw_to_trans[N_BUCKETS];
+ context_map_node_t *trans_to_raw[N_BUCKETS];
+
+ base_classification_t *base_classifications;
+ word_group_t *groups;
+
+ pcre *base_classification_regexp;
+ struct domain *next;
+} domain_t;
+
+static domain_t *domains;
+
+unsigned int
+hash(const char *str) {
+ unsigned int hash = 5381;
+ int c;
+
+ while ((c = *(unsigned const char *)str++))
+ hash = ((hash << 5) + hash) + c;
+
+ return hash;
+}
+
+static void
+add_to_hashtable(context_map_node_t **table, char *key, context_map_t *map) {
+ unsigned int bucket = hash(key) % N_BUCKETS;
+ context_map_node_t **n;
+ for (n = &table[bucket]; *n; n = &(*n)->next)
+ ;
+ *n = malloc(sizeof(context_map_node_t));
+ if (! *n)
+ goto err;
+ (*n)->key = key;
+ (*n)->map = map;
+ (*n)->next = NULL;
+ return;
+err:
+ syslog(LOG_ERR, "add_to_hashtable: allocation error");
+ exit(1);
+}
+
+int
+parse_ebitmap(ebitmap_t *e, ebitmap_t *def, const char *raw) {
+ int inverse = 0;
+ unsigned low, high;
+ int rc = ebitmap_cpy(e, def);
+ if (rc < 0)
+ return rc;
+ while (*raw) {
+ if (*raw == '~') {
+ inverse = 1;
+ raw++;
+ continue;
+ }
+ if (*raw == ',') {
+ inverse = 0;
+ raw++;
+ continue;
+ }
+ if (sscanf(raw,"c%u", &low) != 1)
+ return -1;
+ while(*raw && strchr("c0123456789", *raw))
+ raw++;
+ if (*raw == '.') {
+ raw++;
+ if (sscanf(raw,"c%u", &high) != 1)
+ return -1;
+ while(*raw && strchr("c0123456789", *raw))
+ raw++;
+ } else high = low;
+ while (low <= high) {
+ ebitmap_set_bit(e, low, inverse ? 0 : 1);
+ low++;
+ }
+ }
+ return 0;
+}
+
+word_t *
+create_word(word_t **list, const char *text) {
+ word_t *w = calloc(1, sizeof(word_t));
+ w->text = strdup(text);
+ if (list) {
+ for (; *list; list = &(*list)->next)
+ ;
+ *list = w;
+ }
+
+ return w;
+}
+
+void
+destroy_word(word_t **list, word_t *word) {
+ for (; list && *list; list = &(*list)->next) {
+ if (*list == word) {
+ *list = word->next;
+ break;
+ }
+ }
+ free(word->text);
+ ebitmap_destroy(&word->cat);
+ ebitmap_destroy(&word->normal);
+ ebitmap_destroy(&word->inverse);
+ memset(word, 0, sizeof(word_t));
+ free(word);
+}
+
+word_group_t *
+create_group(word_group_t **list, const char *name) {
+ word_group_t *group = calloc(1, sizeof(word_group_t));
+ group->name = strdup(name);
+ group->join = strdup(" ");
+ group->whitespace = strdup(" ");
+ group->sword = NULL;
+
+ if (list) {
+ for (; *list; list = &(*list)->next)
+ ;
+ *list = group;
+ }
+
+ return group;
+}
+
+void
+destroy_group(word_group_t **list, word_group_t *group) {
+ for (; list && *list; list = &(*list)->next) {
+ if (*list == group) {
+ *list = group->next;
+ break;
+ }
+ }
+ while(group->prefixes) {
+ affix_t *next = group->prefixes->next;
+ free(group->prefixes->text);
+ free(group->prefixes);
+ group->prefixes=next;
+ }
+ while(group->suffixes) {
+ affix_t *next = group->suffixes->next;
+ free(group->suffixes->text);
+ free(group->suffixes);
+ group->suffixes=next;
+ }
+ while(group->words)
+ destroy_word(&group->words, group->words);
+ free(group->whitespace);
+ free(group->name);
+ free(group->sword);
+ free(group->join);
+ pcre_free(group->prefix_regexp);
+ pcre_free(group->word_regexp);
+ pcre_free(group->suffix_regexp);
+ ebitmap_destroy(&group->def);
+ free(group);
+}
+
+domain_t *
+create_domain(const char *name) {
+ domain_t *domain = calloc(1, sizeof(domain_t));
+ domain->name = strdup(name);
+
+ domain_t **d = &domains;
+ for (; *d; d = &(*d)->next)
+ ;
+ *d = domain;
+
+ return domain;
+}
+
+void
+destroy_domain(domain_t *domain) {
+ int i;
+ for (i=0; i < N_BUCKETS; i++) {
+ context_map_node_t *ptr;
+ for (ptr = domain->trans_to_raw[i]; ptr;) {
+ context_map_node_t *t = ptr->next;
+ free(ptr);
+ ptr = t;
+ }
+ domain->trans_to_raw[i] = NULL;
+ }
+ for (i=0; i < N_BUCKETS; i++) {
+ context_map_node_t *ptr;
+ for (ptr = domain->raw_to_trans[i]; ptr;) {
+ context_map_node_t *t = ptr->next;
+ free(ptr->map->raw);
+ free(ptr->map->trans);
+ free(ptr->map);
+ free(ptr);
+ ptr = t;
+ }
+ domain->raw_to_trans[i] = NULL;
+ }
+ while (domain->base_classifications) {
+ base_classification_t *next = domain->base_classifications->next;
+ free(domain->base_classifications->trans);
+ ebitmap_destroy(&domain->base_classifications->level->cat);
+ free(domain->base_classifications->level);
+ free(domain->base_classifications);
+ domain->base_classifications = next;
+ }
+ pcre_free(domain->base_classification_regexp);
+ while (domain->groups)
+ destroy_group(&domain->groups, domain->groups);
+ free(domain->name);
+ free(domain);
+}
+
+int
+add_word(word_group_t *group, char *raw, char *trans) {
+ if (strchr(trans,'-')) {
+ log_error("'%s'is invalid because '-' is illegal in modifiers.\n", trans);
+ exit(1);
+ }
+ word_t *word = create_word(&group->words, trans);
+ int rc = parse_ebitmap(&word->cat, &group->def, raw);
+ if (rc < 0) {
+ log_error(" syntax error in %s\n", raw);
+ destroy_word(&group->words, word);
+ return -1;
+ }
+ ebitmap_andnot(&word->normal, &word->cat, &group->def);
+
+ ebitmap_t temp;
+ ebitmap_xor(&temp, &word->cat, &group->def);
+ ebitmap_and(&word->inverse, &temp, &group->def);
+ ebitmap_destroy(&temp);
+
+ return 0;
+}
+
+mls_level_t *
+parse_raw (const char *raw) {
+ unsigned low, high;
+ mls_level_t *mls = calloc(1, sizeof(mls_level_t));
+ if (!mls) goto err;
+
+ if (sscanf(raw,"s%u", &mls->sens) != 1)
+ goto err;
+ while(*raw && strchr("s0123456789:", *raw))
+ raw++;
+ while (*raw) {
+ if (*raw == ',') {
+ raw++;
+ continue;
+ }
+ if (sscanf(raw,"c%u", &low) != 1)
+ goto err;
+ while(*raw && strchr("c0123456789", *raw))
+ raw++;
+ if (*raw == '.') {
+ raw++;
+ if (sscanf(raw,"c%u", &high) != 1)
+ goto err;
+ while(*raw && strchr("c0123456789", *raw))
+ raw++;
+ } else high = low;
+ while (low <= high) {
+ if (low >= maxbit)
+ maxbit=low+1;
+ if (ebitmap_set_bit(&mls->cat, low, 1) < 0)
+ goto err;
+ low++;
+ }
+ }
+ return mls;
+err:
+ log_error(" parse_raw error %s\n", raw);
+ if (mls) ebitmap_destroy(&mls->cat);
+ free(mls);
+ return NULL;
+}
+
+static int
+add_base_classification(domain_t *domain, char *raw, char *trans) {
+ mls_level_t *level = parse_raw(raw);
+ if (level) {
+ base_classification_t **i;
+ base_classification_t *base_classification = calloc(1, sizeof(base_classification_t));
+ base_classification->trans=strdup(trans);
+ base_classification->level=level;
+
+ for (i=&domain->base_classifications; *i; i=&(*i)->next)
+ ;
+ *i = base_classification;
+ return 0;
+ }
+ log_error(" add_base_classification error %s %s\n", raw, trans);
+ return -1;
+}
+
+static void
+add_cache(domain_t *domain, char *raw, char *trans) {
+ context_map_t *map = malloc(sizeof(context_map_t));
+ if (!map) goto err;
+
+ map->raw = strdup(raw);
+ map->trans = strdup(trans);
+ if (!map->raw || !map->trans) goto err;
+
+ log_debug(" add_cache (%s,%s)\n", raw, trans);
+ add_to_hashtable(domain->raw_to_trans, map->raw, map);
+ add_to_hashtable(domain->trans_to_raw, map->trans, map);
+ return;
+err:
+ log_error("%s: allocation error", "add_cache");
+ exit(1);
+}
+
+static context_map_t *
+find_in_table(context_map_node_t **table, const char *key) {
+ unsigned int bucket = hash(key) % N_BUCKETS;
+ context_map_node_t **n;
+ for (n = &table[bucket]; *n; n = &(*n)->next)
+ if (!strcmp((*n)->key, key))
+ return (*n)->map;
+ return NULL;
+}
+
+char *
+trim(char *str, const char *whitespace) {
+ char *p = str + strlen(str);
+
+ while (p > str && strchr(whitespace, *(p-1)) != NULL)
+ *--p = 0;
+ return str;
+}
+
+char *
+triml(char *str, const char *whitespace) {
+ char *p = str;
+
+ while (*p && (strchr(whitespace, *p) != NULL))
+ p++;
+ return p;
+}
+
+void
+update (char **p, char *const val) {
+ free (*p);
+ *p = strdup(val);
+}
+
+void
+append (affix_t **affixes, const char *val) {
+ affix_t *affix = calloc(1, sizeof(affix_t));
+ affix->text = strdup(val);
+ for (;*affixes; affixes = &(*affixes)->next)
+ ;
+ *affixes = affix;
+}
+
+static int read_translations(const char *filename);
+
+/* Process line from translation file.
+ Remove white space and set raw do data before the "=" and tok to data after it
+ Modifies the data pointed to by the buffer parameter
+ */
+static int
+process_trans(char *buffer) {
+ static domain_t *domain;
+ static word_group_t *group;
+ static int base_classification;
+ static int lineno = 0;
+ char *raw;
+ char *ptr, *tok;
+
+ lineno++;
+ trim(buffer, "\r\n"); /* zap trailing CR, LF */
+ buffer = triml(buffer, "\t "); /* zap leading whitespace */
+ log_debug("%d: %s\n", lineno, buffer);
+ if(*buffer == '#') return 0;
+ if(*buffer == 0) return 0;
+
+ raw = strtok_r(buffer, "=", &ptr);
+ if (!raw || !*raw) {
+ syslog(LOG_ERR, "invalid line %d", lineno);
+ return -1;
+ }
+
+ tok = strtok_r(NULL, "\0", &ptr);
+ if (!tok) {
+ syslog(LOG_ERR, "invalid line %d", lineno);
+ return -1;
+ }
+
+ if (!strcmp(raw, "Domain") || !strcmp(raw, "Table")) {
+ tok = triml(tok, "\t ");
+ trim(tok, "\t ");
+ if (! * tok) {
+ syslog(LOG_ERR, "empty name on line %d", lineno);
+ return -1;
+ }
+ }
+
+ if (!strcmp(raw, "Domain")) {
+ domain = create_domain(tok);
+ group = NULL;
+ return 0;
+ }
+
+ if (!domain) {
+ domain = create_domain("Default");
+ group = NULL;
+ }
+
+ if (!group &&
+ (!strcmp(raw, "Whitespace") || !strcmp(raw, "Join") ||
+ !strcmp(raw, "Prefix") || !strcmp(raw, "Suffix"))) {
+ syslog(LOG_ERR, "expected ModifierGroup declaration on line %d", lineno);
+ return -1;
+ }
+
+ if (!strcmp(raw, "Include")) {
+ if (read_translations(tok) < 0)
+ return -1;
+ } else if (!strcmp(raw, "Base")) {
+ base_classification = 1;
+ } else if (!strcmp(raw, "ModifierGroup")) {
+ group = create_group(&domain->groups, tok);
+ base_classification = 0;
+ } else if (!strcmp(raw, "Whitespace")) {
+ update (&group->whitespace, tok);
+ } else if (!strcmp(raw, "Join")) {
+ update (&group->join, tok);
+ } else if (!strcmp(raw, "Prefix")) {
+ append (&group->prefixes, tok);
+ } else if (!strcmp(raw, "Suffix")) {
+ append (&group->suffixes, tok);
+ } else if (!strcmp(raw, "Default")) {
+ ebitmap_t empty;
+ ebitmap_init(&empty);
+ if (parse_ebitmap(&group->def, &empty, tok) < 0) {
+ syslog(LOG_ERR, "unable to parse Default %d", lineno);
+ return -1;
+ }
+ } else if (group) {
+ add_word(group, raw, tok);
+ } else {
+ if (base_classification) {
+ if (add_base_classification(domain, raw, tok) < 0) {
+ syslog(LOG_ERR, "unable to add base_classification on line %d", lineno);
+ return -1;
+ }
+ }
+ add_cache(domain, raw, tok);
+ }
+/* XXX what errors are meaningful */
+ return 0;
+}
+
+int
+read_translations(const char *filename) {
+ size_t size = 0;
+ char *buffer = NULL;
+ int rval = 0;
+
+ FILE *cfg = fopen(filename,"r");
+ if (!cfg) {
+ syslog(LOG_ERR, "%s file open failed", filename);
+ return -1;
+ }
+
+ __fsetlocking(cfg, FSETLOCKING_BYCALLER);
+ while (getline(&buffer, &size, cfg) > 0) {
+ if( process_trans(buffer) < 0 ) {
+ syslog(LOG_ERR, "%s file read failed", filename);
+ rval = -1;
+ break;
+ }
+ }
+ free(buffer);
+ fclose(cfg);
+ return rval;
+}
+
+int
+init_translations(void) {
+ if (is_selinux_mls_enabled() <= 0)
+ return -1;
+
+ return(read_translations(selinux_translations_path()));
+}
+
+char *
+extract_range(const security_context_t incon) {
+ context_t con = context_new(incon);
+ if (!con) {
+ syslog(LOG_ERR, "extract_range context_new(%s) failed: %s", incon, strerror(errno));
+ return NULL;
+ }
+
+ const char *range = context_range_get(con);
+ if (!range) {
+ syslog(LOG_ERR, "extract_range: context_range_get(%s) failed: %m", incon);
+ context_free(con);
+ return NULL;
+ }
+ char *r = strdup(range);
+ context_free(con);
+ return r;
+}
+
+char *
+new_context_str(const security_context_t incon, const char *range) {
+ char *rcon;
+ context_t con = context_new(incon);
+ if (!con) {
+ syslog(LOG_ERR, "new_context_str: %s %s", incon, strerror(errno));
+ return NULL;
+ }
+ context_range_set(con, range);
+ rcon = strdup(context_str(con));
+ context_free(con);
+ return rcon;
+}
+
+char *
+find_in_hashtable(const char *range, domain_t *domain, context_map_node_t **table) {
+ char *trans = NULL;
+ context_map_t *map = find_in_table(table, range);
+ if (map) {
+ trans = strdup((table == domain->raw_to_trans) ? map->trans: map->raw);
+ log_debug(" found %s in hashtable returning %s\n", range, trans);
+ }
+ return trans;
+}
+
+/* need to escape regexp characters ??? XXX */
+void
+emit_whitespace(char*buffer, char *whitespace) {
+ strcat(buffer, "[");
+ strcat(buffer, whitespace);
+ strcat(buffer, "]");
+}
+
+static int
+size_alpha(const void *p1, const void *p2) {
+ word_t *w1 = *(word_t **)p1;
+ word_t *w2 = *(word_t **)p2;
+ int w1_len=strlen(w1->text);
+ int w2_len=strlen(w2->text);
+ if (w1_len == w2_len)
+ return strcmp(w1->text, w2->text);
+ return (w2_len - w1_len);
+}
+
+void
+build_regexp(pcre **r, char *buffer) {
+ const char *error;
+ int error_offset;
+ if (*r)
+ pcre_free(*r);
+ *r = pcre_compile(buffer, PCRE_CASELESS, &error, &error_offset, NULL);
+ if (error) {
+ log_error("pcre=%s, error=%s\n", buffer, error ? error: "none");
+ }
+ buffer[0] = '\0';
+}
+
+void
+build_regexps(domain_t *domain) {
+ char buffer[1024 * 128];
+ buffer[0] = '\0';
+ base_classification_t *i;
+ word_group_t *g;
+ affix_t *a;
+ word_t *w;
+
+/* whitespace collapse ??? XXX */
+ for (i = domain->base_classifications; i; i = i->next) {
+ strcat(buffer, i->trans);
+ if (i->next) strcat(buffer,"|");
+ }
+ log_debug(">>> %s classification regexp=%s\n", domain->name, buffer);
+ build_regexp(&domain->base_classification_regexp, buffer);
+
+ for (g = domain->groups; g; g = g->next) {
+ if (g->prefixes) {
+ strcat(buffer,"(?:");
+ for (a = g->prefixes; a; a = a->next) {
+ strcat(buffer, a->text);
+ if (a->next) strcat(buffer,"|");
+ }
+ strcat(buffer,")");
+ strcat(buffer,"[ ]+");
+ log_debug(">>> %s %s prefix regexp=%s\n", domain->name, g->name, buffer);
+ build_regexp(&g->prefix_regexp, buffer);
+ }
+
+ if (g->prefixes)
+ strcat(buffer, "^");
+ strcat(buffer, "(?:");
+ g->sword_len=0;
+ for (w = g->words; w; w = w->next) {
+ strcat(buffer,"\\b");
+ strcat(buffer, w->text);
+ strcat(buffer,"\\b");
+ if (w->next) strcat(buffer,"|");
+ g->sword_len++;
+ }
+ g->sword = calloc(g->sword_len, sizeof(word_t *));
+ int i=0;
+ for (w = g->words; w; w = w->next)
+ g->sword[i++]=w;
+ qsort(g->sword, g->sword_len, sizeof(word_t *), size_alpha);
+
+ strcat(buffer,"|");
+ emit_whitespace(buffer, g->whitespace);
+ strcat(buffer,"+");
+
+ strcat(buffer, ")+");
+ if (g->suffixes)
+ strcat(buffer, "$");
+
+ log_debug(">>> %s %s modifier regexp=%s\n", domain->name, g->name, buffer);
+ build_regexp(&g->word_regexp, buffer);
+ if (g->suffixes) {
+ strcat(buffer,"[ ]+");
+ strcat(buffer,"(?:");
+ for (a = g->suffixes; a; a = a->next) {
+ strcat(buffer, a->text);
+ if (a->next) strcat(buffer,"|");
+ }
+ strcat(buffer,")");
+ log_debug(">>> %s %s suffix regexp=%s\n", domain->name, g->name, buffer);
+ build_regexp(&g->suffix_regexp, buffer);
+ }
+ }
+}
+
+/* XXX */
+/* TODO - if bit is set & cleared in one pass - error */
+char *
+compute_raw_from_trans(const char *level, domain_t *domain) {
+ struct timeval startTime;
+ gettimeofday(&startTime, 0);
+
+ int ovector[OVECCOUNT];
+ word_group_t *g;
+ char *work = strdup(level);
+ char *r = NULL;
+ int work_len = strlen(work);
+ mls_level_t *mraw = NULL;
+
+ if (!domain->base_classification_regexp)
+ build_regexps(domain);
+ if (!domain->base_classification_regexp)
+ return NULL;
+ int rc = pcre_exec(domain->base_classification_regexp, 0, work, strlen (work), 0, PCRE_ANCHORED, ovector, OVECCOUNT);
+ if (rc > 0) {
+ const char *match = NULL;
+ pcre_get_substring(work, ovector, rc, 0, &match);
+ base_classification_t *bc;
+ for (bc = domain->base_classifications; bc; bc = bc->next) {
+ if (!strcmp(bc->trans, match)) {
+ mraw = malloc(sizeof(mls_level_t));
+ mls_level_cpy(mraw, bc->level);
+ break;
+ }
+ }
+
+ memset(work + ovector[0], '#', ovector[1] - ovector[0]);
+ char *p=work + ovector[0] + ovector[1];
+ while (*p && (strchr(" ", *p) != NULL))
+ *p++ = '#';
+ pcre_free((char *)match);
+ }
+
+ if (mraw == NULL) {
+ free(work);
+ return NULL;
+ }
+
+ int complete = 0;
+ int change = 1;
+ while(change && !complete) {
+ change = 0;
+ for (g = domain->groups; g && !change && !complete; g = g->next) {
+ int prefix = 0, suffix = 0;
+ int prefix_offset = 0, prefix_len = 0;
+ int suffix_offset = 0, suffix_len = 0;
+ if (g->prefix_regexp) {
+ int rc = pcre_exec(g->prefix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT);
+ if (rc > 0) {
+ prefix = 1;
+ prefix_offset = ovector[0];
+ prefix_len = ovector[1] - ovector[0];
+ }
+ }
+ if (g->suffix_regexp) {
+ int rc = pcre_exec(g->suffix_regexp, 0, work, work_len, 0, 0, ovector, OVECCOUNT);
+ if (rc > 0) {
+ suffix = 1;
+ suffix_offset = ovector[0];
+ suffix_len = ovector[1] - ovector[0];
+ }
+ }
+
+/* anchors prefix ^, suffix $ */
+ if (((!g->prefixes && !g->suffixes) ||
+ (g->prefixes && prefix) ||
+ (g->suffixes && suffix)) &&
+ g->word_regexp) {
+ char *s = work + prefix_offset + prefix_len;
+ int l = (suffix_len ? suffix_offset : work_len) - prefix_len - prefix_offset;
+ int rc = pcre_exec(g->word_regexp, 0, s, l, 0,
+ 0, ovector, OVECCOUNT);
+ if (rc > 0) {
+ const char *match;
+ pcre_get_substring(s, ovector, rc, 0, &match);
+ trim((char *)match, g->whitespace);
+ if (*match) {
+ char *p = triml((char *)match, g->whitespace);
+ while (p && *p) {
+ int plen = strlen(p);
+ int i;
+ for (i = 0; i < g->sword_len; i++) {
+ word_t *w = g->sword[i];
+ int wlen = strlen(w->text);
+ if (plen >= wlen && !strncmp(w->text, p, strlen(w->text))){
+ ebitmap_t set, clear, tmp;
+ ebitmap_andnot(&set, &w->cat, &g->def);
+
+ ebitmap_xor(&tmp, &w->cat, &g->def);
+ ebitmap_and(&clear, &tmp, &g->def);
+
+ ebitmap_union(&mraw->cat, &set);
+
+ ebitmap_destroy(&tmp);
+ ebitmap_cpy(&tmp, &mraw->cat);
+ ebitmap_destroy(&mraw->cat);
+ ebitmap_andnot(&mraw->cat, &tmp, &clear);
+
+ ebitmap_destroy(&tmp);
+ ebitmap_destroy(&set);
+ ebitmap_destroy(&clear);
+ p += strlen(w->text);
+ change++;
+ break;
+ }
+ }
+ if (i == g->sword_len) {
+ syslog(LOG_ERR, "conversion error");
+ break;
+ }
+ p = triml(p, g->whitespace);
+ }
+ memset(work + prefix_offset, '#', prefix_len);
+ memset(work + suffix_offset, '#', suffix_len);
+ memset(s + ovector[0], '#', ovector[1] - ovector[0]);
+ }
+ pcre_free((void *)match);
+ }
+ }
+ complete=1;
+ char *p = work;
+ while(*p) {
+ if (isalnum(*p++)) {
+ complete=0;
+ break;
+ }
+ }
+ }
+ }
+ free(work);
+ if (complete)
+ r = mls_level_to_string(mraw);
+ mls_level_destroy(mraw);
+ free(mraw);
+ struct timeval stopTime;
+ gettimeofday(&stopTime, 0);
+ long int ms;
+ if (startTime.tv_usec > stopTime.tv_usec)
+ ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
+ else
+ ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000);
+
+ return r;
+}
+
+/* XXX SLOW */
+char *
+compute_trans_from_raw(const char *level, domain_t *domain) {
+ struct timeval startTime;
+ gettimeofday(&startTime, 0);
+
+ char *rval = NULL;
+ if (!level)
+ return NULL;
+ mls_level_t *l = parse_raw(level);
+ if (!l)
+ return NULL;
+ log_debug(" compute_trans_from_raw raw = %s\n", level);
+
+/* HACK XXX - should be function, should derive from config*/
+ int doInverse = l->sens > 0;
+
+ word_group_t *groups = NULL;
+ base_classification_t *bc, *last = NULL;
+ int done = 0;
+ for (bc = domain->base_classifications; bc && !done; bc = bc->next) {
+ if (l->sens == bc->level->sens) {
+ /* skip if alias of last bc */
+ if (last &&
+ last->level->sens == bc->level->sens &&
+ ebitmap_cmp(&last->level->cat, &bc->level->cat) == 0)
+ continue;
+
+ /* compute bits not consumed by base classification */
+ ebitmap_t unhandled, orig_unhandled;
+ ebitmap_xor(&unhandled, &l->cat, &bc->level->cat);
+ ebitmap_cpy(&orig_unhandled, &unhandled);
+
+ /* prebuild groups */
+ word_group_t *g;
+ for (g = domain->groups; g; g = g->next) {
+ word_group_t **t;
+ for (t = &groups; *t; t = &(*t)->next)
+ if (!strcmp(g->name, (*t)->name))
+ break;
+
+ if (! *t) {
+ word_group_t *wg = create_group(&groups, g->name);
+ if (g->prefixes)
+ append (&wg->prefixes, g->prefixes->text);
+ if (g->suffixes)
+ append (&wg->suffixes, g->suffixes->text);
+ if (g->join)
+ update (&wg->join, g->join);
+ }
+ }
+
+ int loops, hamming, change=1;
+ for (loops = 50; ebitmap_cardinality(&unhandled) && loops > 0 && change; loops--) {
+ change = 0;
+ hamming = 10000;
+ ebitmap_t handled, nothandled;
+ ebitmap_xor(&handled, &unhandled, &orig_unhandled);
+ ebitmap_not(&nothandled, &handled);
+ word_group_t *currentGroup = NULL;
+ word_t *currentWord = NULL;
+ for (g = domain->groups; g && hamming; g = g->next) {
+ word_t *w;
+ for (w = g->words; w && hamming; w = w->next) {
+ int cardinality = ebitmap_cardinality(&w->normal);
+ /* If the word is all inverse bits and the level does not have inverse bits - skip */
+ if (cardinality && !doInverse) {
+ continue;
+ }
+
+ /* if only unhandled bits are different */
+ ebitmap_t temp;
+ ebitmap_t bit_diff;
+ ebitmap_or(&temp, &w->normal, &w->inverse);
+ ebitmap_and(&bit_diff, &temp, &nothandled);
+ ebitmap_destroy(&temp);
+// xor bit_diff handled?
+ ebitmap_and(&temp, &bit_diff, &unhandled);
+ if (ebitmap_cmp(&bit_diff, &temp)) {
+ int h = hamming_distance(&bit_diff, &unhandled);
+ if (h < hamming) {
+ hamming = h;
+ currentGroup = g;
+ currentWord = w;
+ }
+ }
+ ebitmap_destroy(&bit_diff);
+ ebitmap_destroy(&temp);
+ }
+ }
+ ebitmap_destroy(&handled);
+ ebitmap_destroy(&nothandled);
+
+ if (currentWord) {
+ ebitmap_t bit_diff;
+ ebitmap_xor(&bit_diff, &currentWord->cat, &bc->level->cat);
+
+ ebitmap_t temp;
+ ebitmap_cpy(&temp, &unhandled);
+ ebitmap_destroy(&unhandled);
+ ebitmap_andnot(&unhandled, &temp, &bit_diff);
+
+ ebitmap_destroy(&bit_diff);
+ ebitmap_destroy(&temp);
+
+ word_group_t **t;
+ for (t = &groups; *t; t = &(*t)->next)
+ if (!strcmp(currentGroup->name, (*t)->name))
+ break;
+ create_word(&(*t)->words, currentWord->text);
+ change++;
+ }
+ }
+
+ done = (ebitmap_cardinality(&unhandled) == 0);
+ ebitmap_destroy(&unhandled);
+ ebitmap_destroy(&orig_unhandled);
+ if (done) {
+ char buffer[9999];
+ buffer[0] = 0;
+ strcat(buffer, bc->trans);
+ strcat(buffer, " ");
+ word_group_t *g;
+ for (g=groups; g; g = g->next) {
+ if (g->words && g->prefixes) {
+ strcat(buffer, g->prefixes->text);
+ strcat(buffer, " ");
+ }
+ word_t *w;
+ for (w=g->words; w; w = w->next) {
+ strcat(buffer, w->text);
+ if (w->next)
+ strcat(buffer, g->join);
+ }
+ if (g->words && g->suffixes) {
+ strcat(buffer, " ");
+ strcat(buffer, g->suffixes->text);
+ }
+ word_group_t *n = g->next;
+ while(g->words && n) {
+ if (n->words) {
+ strcat(buffer, " ");
+ break;
+ }
+ n = n->next;
+ }
+ }
+ rval = strdup(buffer);
+ }
+ /* clean up */
+ while (groups)
+ destroy_group(&groups, groups);
+ }
+ last = bc;
+ }
+ if (l) {
+ mls_level_destroy(l);
+ free(l);
+ }
+
+ struct timeval stopTime;
+ gettimeofday(&stopTime, 0);
+ long int ms;
+ if (startTime.tv_usec > stopTime.tv_usec)
+ ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
+ else
+ ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000);
+
+ return rval;
+}
+
+int
+trans_context(const security_context_t incon, security_context_t *rcon) {
+ char *trans = NULL;
+ *rcon = NULL;
+
+ struct timeval startTime;
+ gettimeofday(&startTime, 0);
+
+ log_debug(" trans_context input = %s\n", incon);
+ char *range = extract_range(incon);
+ if (!range) return -1;
+
+ domain_t *domain = domains;
+ for (;domain; domain = domain->next) {
+ trans = find_in_hashtable(range, domain, domain->raw_to_trans);
+ if (trans) break;
+
+ /* try split and translate */
+ char *lrange = NULL, *urange = NULL;
+ char *ltrans = NULL, *utrans = NULL;
+ char *dashp = strchr(range,'-');
+ if (dashp) {
+ *dashp = 0;
+ lrange = range;
+ urange = dashp+1;
+ } else {
+ trans = compute_trans_from_raw(range, domain);
+ if (trans)
+ add_cache(domain, range, trans);
+ }
+
+ if (lrange && urange) {
+ ltrans = find_in_hashtable(lrange, domain, domain->raw_to_trans);
+ if (! ltrans) {
+ ltrans = compute_trans_from_raw(lrange, domain);
+ if (ltrans)
+ add_cache(domain, lrange, ltrans);
+ }
+
+ utrans = find_in_hashtable(urange, domain, domain->raw_to_trans);
+ if (! utrans) {
+ utrans = compute_trans_from_raw(urange, domain);
+ if (utrans)
+ add_cache(domain, urange, utrans);
+ }
+
+ if (ltrans && utrans) {
+ if (strcmp(ltrans, utrans) == 0) {
+ if (asprintf(&trans, "%s", ltrans) < 0) {
+ log_error("asprintf failed %s", strerror(errno));
+ exit(1);
+ }
+ } else {
+ if (asprintf(&trans, "%s-%s", ltrans, utrans) < 0) {
+ log_error("asprintf failed %s", strerror(errno));
+ exit(1);
+ }
+ }
+ free(ltrans);
+ free(utrans);
+ break;
+ }
+ }
+ if (dashp)
+ *dashp = '-';
+ }
+
+ if (trans) {
+ *rcon = new_context_str(incon, trans);
+ free(trans);
+ } else {
+ *rcon = new_context_str(incon, range);
+ }
+ free(range);
+
+ struct timeval stopTime;
+ gettimeofday(&stopTime, 0);
+ long int ms;
+ if (startTime.tv_usec > stopTime.tv_usec)
+ ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
+ else
+ ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000);
+
+ log_debug(" trans_context input='%s' output='%s in %ld ms'\n", incon, *rcon, ms);
+ return 0;
+}
+
+int
+untrans_context(const security_context_t incon, security_context_t *rcon) {
+ char *raw = NULL;
+ *rcon = NULL;
+
+ struct timeval startTime;
+ gettimeofday(&startTime, 0);
+
+ log_debug(" untrans_context incon = %s\n", incon);
+ char *range = extract_range(incon);
+ if (!range) return -1;
+ log_debug(" untrans_context range = %s\n", range);
+
+ domain_t *domain = domains;
+ for (;domain; domain = domain->next) {
+ raw = find_in_hashtable(range, domain, domain->trans_to_raw);
+ if (raw) break;
+
+ /* try split and translate */
+ char *lrange = NULL, *urange = NULL;
+ char *lraw = NULL, *uraw = NULL;
+ char *dashp = strchr(range,'-');
+ if (dashp) {
+ *dashp = 0;
+ lrange = range;
+ urange = dashp+1;
+ } else {
+ raw = compute_raw_from_trans(range, domain);
+ if (raw) {
+ char *canonical = find_in_hashtable(raw, domain, domain->raw_to_trans);
+ if (!canonical) {
+ canonical = compute_trans_from_raw(raw, domain);
+ if (canonical)
+ add_cache(domain, raw, canonical);
+ }
+ if (canonical)
+ free(canonical);
+ add_cache(domain, raw, range);
+ }
+ }
+
+ if (lrange && urange) {
+ lraw = find_in_hashtable(lrange, domain, domain->trans_to_raw);
+ if (! lraw) {
+ lraw = compute_raw_from_trans(lrange, domain);
+ if (lraw) {
+ char *canonical = find_in_hashtable(lraw, domain, domain->raw_to_trans);
+ if (!canonical) {
+ canonical = compute_trans_from_raw(lraw, domain);
+ if (canonical)
+ add_cache(domain, lraw, canonical);
+ }
+ if (canonical)
+ free(canonical);
+ add_cache(domain, lraw, lrange);
+ }
+ }
+
+ uraw = find_in_hashtable(urange, domain, domain->trans_to_raw);
+ if (! uraw) {
+ uraw = compute_raw_from_trans(urange, domain);
+ if (uraw) {
+ char *canonical = find_in_hashtable(uraw, domain, domain->raw_to_trans);
+ if (!canonical) {
+ canonical = compute_trans_from_raw(uraw, domain);
+ if (canonical)
+ add_cache(domain, uraw, canonical);
+ }
+ if (canonical)
+ free(canonical);
+ add_cache(domain, uraw, urange);
+ }
+ }
+
+
+ if (lraw && uraw) {
+ if (strcmp(lraw, uraw) == 0) {
+ if (asprintf(&raw, "%s", lraw) < 0) {
+ log_error("asprintf failed %s", strerror(errno));
+ exit(1);
+ }
+ } else {
+ if (asprintf(&raw, "%s-%s", lraw, uraw) < 0) {
+ log_error("asprintf failed %s", strerror(errno));
+ exit(1);
+ }
+ }
+ free(lraw);
+ free(uraw);
+ break;
+ }
+ if (lraw)
+ free(lraw);
+ if (uraw)
+ free(uraw);
+ *dashp = '-';
+ }
+ }
+
+ if (raw) {
+ *rcon = new_context_str(incon, raw);
+ free(raw);
+ } else {
+ *rcon = new_context_str(incon, range);
+ }
+ free(range);
+
+ struct timeval stopTime;
+ gettimeofday(&stopTime, 0);
+ long int ms;
+ if (startTime.tv_usec > stopTime.tv_usec)
+ ms = (stopTime.tv_sec - startTime.tv_sec - 1) * 1000 + (stopTime.tv_usec/1000 + 1000 - startTime.tv_usec/1000);
+ else
+ ms = (stopTime.tv_sec - startTime.tv_sec ) * 1000 + (stopTime.tv_usec/1000 - startTime.tv_usec/1000);
+
+ log_debug(" untrans_context input='%s' output='%s' n %ld ms\n", incon, *rcon, ms);
+ return 0;
+}
+
+void
+finish_context_translations(void) {
+ while(domains) {
+ domain_t *next = domains->next;
+ destroy_domain(domains);
+ domains = next;
+ }
+}
+
diff --git a/src/mcstrans.h b/src/mcstrans.h
new file mode 100644
index 0000000..a2f68c1
--- /dev/null
+++ b/src/mcstrans.h
@@ -0,0 +1,9 @@
+/* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
+
+#include <selinux/selinux.h>
+
+extern int init_translations(void);
+extern void finish_context_translations(void);
+extern int trans_context(const security_context_t, security_context_t *);
+extern int untrans_context(const security_context_t, security_context_t *);
+
diff --git a/src/mcstrans.init b/src/mcstrans.init
new file mode 100644
index 0000000..89f6ad6
--- /dev/null
+++ b/src/mcstrans.init
@@ -0,0 +1,112 @@
+#!/bin/bash
+#
+# mcstransd This starts and stops mcstransd
+#
+# chkconfig: - 08 87
+# description: This starts the SELinux Context Translation System Daemon
+#
+# processname: /sbin/mcstransd
+# pidfile: /var/run/mcstransd.pid
+#
+# Return values according to LSB for all commands but status:
+# 0 - success
+# 1 - generic or unspecified error
+# 2 - invalid or excess argument(s)
+# 3 - unimplemented feature (e.g. "reload")
+# 4 - insufficient privilege
+# 5 - program is not installed
+# 6 - program is not configured
+# 7 - program is not running
+
+PATH=/sbin:/bin:/usr/bin:/usr/sbin
+prog="mcstransd"
+
+# Source function library.
+. /etc/init.d/functions
+
+# Allow anyone to run status
+if [ "$1" = "status" ] ; then
+ status $prog
+ RETVAL=$?
+ exit $RETVAL
+fi
+
+# Check that we are root ... so non-root users stop here
+test $EUID = 0 || exit 4
+
+# If selinux is not enabled, return success
+test -x /usr/sbin/selinuxenabled && /usr/sbin/selinuxenabled || exit 0
+
+RETVAL=0
+
+start(){
+ test -x /sbin/mcstransd || exit 5
+ echo -n $"Starting $prog: "
+ if status $prog > /dev/null; then
+ echo -n $"$prog: already running"
+ failure
+ echo
+ return 1
+ fi
+
+ unset HOME MAIL USER USERNAME
+ daemon $prog "$EXTRAOPTIONS"
+ RETVAL=$?
+ echo
+ if test $RETVAL = 0 ; then
+ touch /var/lock/subsys/mcstrans
+ fi
+ return $RETVAL
+}
+
+stop(){
+ echo -n $"Stopping $prog: "
+ killproc $prog
+ RETVAL=$?
+ echo
+ rm -f /var/lock/subsys/mcstrans
+ return $RETVAL
+}
+
+reload(){
+ echo -n $"Reloading configuration: "
+ killproc $prog -HUP
+ RETVAL=$?
+ echo
+ return $RETVAL
+}
+
+restart(){
+ stop
+ start
+}
+
+condrestart(){
+ [ -e /var/lock/subsys/mcstrans ] && restart
+ return 0
+}
+
+
+# See how we were called.
+case "$1" in
+ start)
+ start
+ ;;
+ stop)
+ stop
+ ;;
+ restart)
+ restart
+ ;;
+ reload)
+ reload
+ ;;
+ condrestart)
+ condrestart
+ ;;
+ *)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|reload|rotate}"
+ RETVAL=3
+esac
+
+exit $RETVAL
diff --git a/src/mcstransd.c b/src/mcstransd.c
new file mode 100644
index 0000000..726b851
--- /dev/null
+++ b/src/mcstransd.c
@@ -0,0 +1,609 @@
+/* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <syslog.h>
+#include <selinux/selinux.h>
+#include <sys/types.h>
+#include <sys/capability.h>
+#include <sys/resource.h>
+#include "mcstrans.h"
+
+#ifdef UNUSED
+#elif defined(__GNUC__)
+# define UNUSED(x) UNUSED_ ## x __attribute__((unused))
+#elif defined(__LCLINT__)
+# define UNUSED(x) /*@unused@*/ x
+#else
+# define UNUSED(x) x
+#endif
+
+#define SETRANS_UNIX_SOCKET "/var/run/setrans/.setrans-unix"
+
+#define SETRANS_INIT 1
+#define RAW_TO_TRANS_CONTEXT 2
+#define TRANS_TO_RAW_CONTEXT 3
+#define MAX_DATA_BUF 4096
+#define MAX_DESCRIPTORS 8192
+
+#ifdef DEBUG
+//#define log_debug(fmt, ...) syslog(LOG_DEBUG, fmt, __VA_ARGS__)
+#define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
+#else
+#define log_debug(fmt, ...) ;
+#endif
+
+extern int init_translations(void);
+extern void finish_context_translations(void);
+extern int trans_context(const security_context_t, security_context_t *);
+extern int untrans_context(const security_context_t, security_context_t *);
+
+#define SETRANSD_PATHNAME "/sbin/mcstransd"
+
+/* name of program (for error messages) */
+#define SETRANSD_PROGNAME "mcstransd"
+
+static int sockfd = -1; /* socket we are listening on */
+
+static volatile int restart_daemon = 0;
+static void cleanup_exit(int ret) __attribute__ ((noreturn));
+static void
+cleanup_exit(int ret)
+{
+ finish_context_translations();
+ if (sockfd >=0)
+ (void)unlink(SETRANS_UNIX_SOCKET);
+
+ log_debug("%s\n", "cleanup_exit");
+
+ exit(ret);
+}
+
+static void clean_exit(void);
+static __attribute__((noreturn)) void clean_exit(void)
+{
+ log_debug("%s\n", "clean_exit");
+ cleanup_exit(0);
+}
+
+/*
+ * Convert raw label portion of a security context to translated label
+ * Returns: 0 on success, 1 on failure
+ */
+static int
+raw_to_trans_context(char *in, char **out, char *UNUSED(pcon))
+{
+ log_debug("raw_to_trans_context=%s\n", in);
+ *out = NULL;
+
+ /* TODO: Check if MLS clearance (in "pcon") dominates the MLS label
+ * (in "in").
+ */
+
+ return trans_context(in, out);
+}
+
+
+/*
+ * Convert translated label of a security context to raw label
+ * Returns: 0 on success, 1 on failure
+ */
+static int
+trans_to_raw_context(char *in, char **out, char *UNUSED(pcon))
+{
+ log_debug("trans_to_raw_context=%s\n", in);
+
+ *out = NULL;
+
+ /* TODO: Check if MLS clearance (in "pcon") dominates the MLS label
+ * (in "in").
+ */
+
+ return untrans_context(in, out);
+}
+
+static int
+send_response(int fd, uint32_t function, char *data, int32_t ret_val)
+{
+ struct iovec resp_hdr[3];
+ uint32_t data_size;
+ struct iovec resp_data;
+ ssize_t count;
+
+ if (!data)
+ data = "";
+
+ data_size = strlen(data) + 1;
+
+ resp_hdr[0].iov_base = &function;
+ resp_hdr[0].iov_len = sizeof(function);
+ resp_hdr[1].iov_base = &data_size;
+ resp_hdr[1].iov_len = sizeof(data_size);
+ resp_hdr[2].iov_base = &ret_val;
+ resp_hdr[2].iov_len = sizeof(ret_val);
+
+ while (((count = writev(fd, resp_hdr, 3)) < 0) && (errno == EINTR));
+ if (count != (sizeof(function) + sizeof(data_size) + sizeof(ret_val))) {
+ syslog(LOG_ERR, "Failed to write response header");
+ return -1;
+ }
+
+ resp_data.iov_base = data;
+ resp_data.iov_len = data_size;
+
+ while (((count = writev(fd, &resp_data, 1)) < 0) && (errno == EINTR));
+ if (count < 0 || (size_t)count != data_size) {
+ syslog(LOG_ERR, "Failed to write response data");
+ return -1;
+ }
+
+ return ret_val;
+}
+
+static int
+get_peer_pid(int fd, pid_t *pid)
+{
+ int ret;
+ socklen_t size = sizeof(struct ucred);
+ struct ucred peercred;
+
+ /* get the context of the requesting process */
+ ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &size);
+ if (ret < 0) {
+ syslog(LOG_ERR, "Failed to get PID of client process");
+ return -1;
+ }
+ *pid = peercred.pid;
+ return ret;
+}
+
+
+static int
+get_peer_con(int fd, char **peercon)
+{
+ int ret;
+ pid_t pid;
+ ret = get_peer_pid(fd, &pid);
+ if (ret)
+ return -1;
+ ret = getpidcon_raw(pid, peercon);
+ if (ret) {
+ syslog(LOG_ERR,
+ "Failed to get context of client process (pid=%u)",
+ pid);
+ return -1;
+ }
+ return 0;
+}
+
+static int
+process_request(int fd, uint32_t function, char *data1, char *UNUSED(data2))
+{
+ int32_t result;
+ char *out = NULL;
+ char *peercon = NULL;
+ int ret;
+
+ switch (function) {
+ case SETRANS_INIT:
+ result = 0;
+ ret = send_response(fd, function, NULL, result);
+ break;
+ case RAW_TO_TRANS_CONTEXT:
+ ret = get_peer_con(fd, &peercon);
+ if (ret)
+ return ret;
+ result = raw_to_trans_context(data1, &out, peercon);
+ if (result) {
+ pid_t pid = 0;
+ get_peer_pid(fd, &pid);
+ syslog(LOG_ERR, "Invalid raw_to_trans_context request from=%u", pid);
+ }
+ ret = send_response(fd, function, out, result);
+ break;
+ case TRANS_TO_RAW_CONTEXT:
+ ret = get_peer_con(fd, &peercon);
+ if (ret)
+ return ret;
+ result = trans_to_raw_context(data1, &out, peercon);
+ if (result) {
+ pid_t pid = 0;
+ get_peer_pid(fd, &pid);
+ syslog(LOG_ERR, "Invalid trans_to_raw_context request from=%u", pid);
+ }
+ ret = send_response(fd, function, out, result);
+ break;
+ default:
+ syslog(LOG_ERR, "Invalid request func=%d", function);
+ ret = -1;
+ break;
+ }
+
+ free(out);
+ freecon(peercon);
+
+ return ret;
+}
+
+static int
+service_request(int fd)
+{
+ struct iovec req_hdr[3];
+ uint32_t function;
+ uint32_t data1_size;
+ uint32_t data2_size;
+ struct iovec req_data[2];
+ char *data1;
+ char *data2;
+ int ret;
+ ssize_t count;
+
+ req_hdr[0].iov_base = &function;
+ req_hdr[0].iov_len = sizeof(function);
+ req_hdr[1].iov_base = &data1_size;
+ req_hdr[1].iov_len = sizeof(data1_size);
+ req_hdr[2].iov_base = &data2_size;
+ req_hdr[2].iov_len = sizeof(data2_size);
+
+ while (((count = readv(fd, req_hdr, 3)) < 0) && (errno == EINTR));
+ if (count <= 0) {
+ return 1;
+ }
+ if (count != (sizeof(function) + sizeof(data1_size) +
+ sizeof(data2_size) )) {
+ log_debug("Failed to read request header %d != %u\n",(int)count,
+ (unsigned)(sizeof(function) + sizeof(data1_size) +
+ sizeof(data2_size) ));
+ return -1;
+ }
+
+ if (!data1_size || !data2_size || data1_size > MAX_DATA_BUF ||
+ data2_size > MAX_DATA_BUF ) {
+ log_debug("Header invalid data1_size=%u data2_size=%u\n",
+ data1_size, data2_size);
+ return -1;
+ }
+
+ data1 = malloc(data1_size);
+ if (!data1) {
+ log_debug("Could not allocate %d bytes\n", data1_size);
+ return -1;
+ }
+ data2 = malloc(data2_size);
+ if (!data2) {
+ free(data1);
+ log_debug("Could not allocate %d bytes\n", data2_size);
+ return -1;
+ }
+
+ req_data[0].iov_base = data1;
+ req_data[0].iov_len = data1_size;
+ req_data[1].iov_base = data2;
+ req_data[1].iov_len = data2_size;
+
+ while (((count = readv(fd, req_data, 2)) < 0) && (errno == EINTR));
+ if (count <= 0 || (size_t)count != (data1_size + data2_size) ||
+ data1[data1_size - 1] != '\0' || data2[data2_size - 1] != '\0') {
+ free(data1);
+ free(data2);
+ log_debug("Failed to read request data (%d)\n", (int)count);
+ return -1;
+ }
+
+ ret = process_request(fd, function, data1, data2);
+
+ free(data1);
+ free(data2);
+
+ return ret;
+}
+
+static int
+add_pollfd(struct pollfd **ufds, int *nfds, int connfd)
+{
+ int ii = 0;
+
+ /* First see if we can find an already invalidated ufd */
+ for (ii = 0; ii < *nfds; ii++) {
+ if ((*ufds)[ii].fd == -1)
+ break;
+ }
+
+ if (ii == *nfds) {
+ struct pollfd *tmp = (struct pollfd *)realloc(*ufds,
+ (*nfds+1)*sizeof(struct pollfd));
+ if (!tmp) {
+ syslog(LOG_ERR, "realloc failed for %d fds", *nfds+1);
+ return -1;
+ }
+
+ *ufds = tmp;
+ (*nfds)++;
+ }
+
+ (*ufds)[ii].fd = connfd;
+ (*ufds)[ii].events = POLLIN|POLLPRI;
+ (*ufds)[ii].revents = 0;
+
+ return 0;
+}
+
+static void
+adj_pollfds(struct pollfd **ufds, int *nfds)
+{
+ int ii, jj;
+
+ jj = 0;
+ for (ii = 0; ii < *nfds; ii++) {
+ if ((*ufds)[ii].fd != -1) {
+ if (jj < ii)
+ (*ufds)[jj] = (*ufds)[ii];
+ jj++;
+ }
+ }
+ *nfds = jj;
+}
+
+static int
+process_events(struct pollfd **ufds, int *nfds)
+{
+ int ii = 0;
+ int ret = 0;
+
+ for (ii = 0; ii < *nfds; ii++) {
+ short revents = (*ufds)[ii].revents;
+ int connfd = (*ufds)[ii].fd;
+
+ if (revents & (POLLIN | POLLPRI)) {
+ if (connfd == sockfd) {
+
+ /* Probably received a connection */
+ if ((connfd = accept(sockfd, NULL, NULL)) < 0) {
+ syslog(LOG_ERR, "accept() failed: %m");
+ return -1;
+ }
+
+ if (add_pollfd(ufds, nfds, connfd)) {
+ syslog(LOG_ERR,
+ "Failed to add fd (%d) to poll list\n",
+ connfd);
+ return -1;
+ }
+ } else {
+ ret = service_request(connfd);
+ if (ret) {
+ if (ret < 0) {
+ syslog(LOG_ERR,
+ "Servicing of request "
+ "failed for fd (%d)\n",
+ connfd);
+ }
+ /* Setup pollfd for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+ /* So we don't get bothered later */
+ revents = revents & ~(POLLHUP);
+ }
+ }
+ revents = revents & ~(POLLIN | POLLPRI);
+ }
+ if (revents & POLLHUP) {
+ log_debug("The connection with fd (%d) hung up\n",
+ connfd);
+
+ /* Set the pollfd up for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+
+ revents = revents & ~(POLLHUP);
+ }
+ if (revents) {
+ syslog(LOG_ERR, "Unknown/error events (%x) encountered"
+ " for fd (%d)\n", revents, connfd);
+
+ /* Set the pollfd up for deletion later. */
+ (*ufds)[ii].fd = -1;
+ close(connfd);
+ }
+
+ (*ufds)[ii].revents = 0;
+ }
+
+ /* Delete any invalidated ufds */
+ adj_pollfds(ufds, nfds);
+
+ return 0;
+}
+
+static void
+process_connections(void) __attribute__ ((noreturn));
+
+static void
+process_connections(void)
+{
+ int ret = 0;
+ int nfds = 1;
+
+ struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd));
+ if (!ufds) {
+ syslog(LOG_ERR, "Failed to allocate a pollfd");
+ cleanup_exit(1);
+ }
+ ufds[0].fd = sockfd;
+ ufds[0].events = POLLIN|POLLPRI;
+ ufds[0].revents = 0;
+
+ while (1) {
+ if (restart_daemon) {
+ syslog(LOG_NOTICE, "Reload Translations");
+ finish_context_translations();
+ if (init_translations()) {
+ syslog(LOG_ERR, "Failed to initialize label translations");
+ cleanup_exit(1);
+ }
+ restart_daemon = 0;
+ }
+
+ ret = poll(ufds, nfds, -1);
+ if (ret < 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ syslog(LOG_ERR, "poll() failed: %m");
+ cleanup_exit(1);
+ }
+
+ ret = process_events(&ufds, &nfds);
+ if (ret) {
+ syslog(LOG_ERR, "Error processing events");
+ cleanup_exit(1);
+ }
+ }
+}
+
+static void
+sigterm_handler(int sig) __attribute__ ((noreturn));
+
+static void
+sigterm_handler(int UNUSED(sig))
+{
+ cleanup_exit(0);
+}
+
+static void
+sighup_handler(int UNUSED(sig))
+{
+ restart_daemon = 1;
+}
+
+static void
+initialize(void)
+{
+ struct sigaction act;
+ struct sockaddr_un addr;
+ struct rlimit rl ;
+
+ if (init_translations()) {
+ syslog(LOG_ERR, "Failed to initialize label translations");
+ cleanup_exit(1);
+ }
+
+ /* the socket will be unlinked when the daemon terminates */
+ act.sa_handler = sigterm_handler;
+ sigemptyset(&act.sa_mask);
+ sigaddset(&act.sa_mask, SIGINT);
+ sigaddset(&act.sa_mask, SIGQUIT);
+ sigaddset(&act.sa_mask, SIGTERM);
+ sigaddset(&act.sa_mask, SIGHUP);
+ act.sa_flags = 0;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGQUIT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+
+ /* restart the daemon on SIGHUP */
+ act.sa_handler = sighup_handler;
+ sigemptyset(&act.sa_mask);
+ sigaddset(&act.sa_mask, SIGINT);
+ sigaddset(&act.sa_mask, SIGQUIT);
+ sigaddset(&act.sa_mask, SIGTERM);
+ act.sa_flags = 0;
+ sigaction(SIGHUP, &act, NULL);
+
+ /* ignore SIGPIPE (in case a client terminates after sending request) */
+ act.sa_handler = SIG_IGN;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGPIPE, &act, NULL);
+
+ atexit(clean_exit);
+
+ sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ syslog(LOG_ERR, "socket() failed: %m");
+ cleanup_exit(1);
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path) - 1);
+
+ (void)unlink(SETRANS_UNIX_SOCKET);
+
+ if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ syslog(LOG_ERR, "bind() failed: %m");
+ cleanup_exit(1);
+ }
+
+ if (listen(sockfd, SOMAXCONN) < 0) {
+ syslog(LOG_ERR, "listen() failed: %m");
+ cleanup_exit(1);
+ }
+
+ if (chmod(SETRANS_UNIX_SOCKET, S_IRWXU | S_IRWXG | S_IRWXO)) {
+ syslog(LOG_ERR, "chmod() failed: %m");
+ cleanup_exit(1);
+ }
+
+ /* Raise the rlimit for file descriptors... */
+ rl.rlim_max = MAX_DESCRIPTORS;
+ rl.rlim_cur = MAX_DESCRIPTORS;
+ setrlimit(RLIMIT_NOFILE, &rl);
+
+}
+
+void dropprivs(void)
+{
+ cap_t new_caps;
+
+ new_caps = cap_init();
+ if (cap_set_proc(new_caps)) {
+ syslog(LOG_ERR, "Error dropping capabilities, aborting: %s\n",
+ strerror(errno));
+ exit(-1);
+ }
+ cap_free(new_caps);
+}
+
+int
+main(int UNUSED(argc), char *argv[])
+{
+#ifndef DEBUG
+ /* Make sure we are root */
+ if (getuid() != 0) {
+ syslog(LOG_ERR, "You must be root to run this program.\n");
+ return 4;
+ }
+#endif
+
+ openlog(SETRANSD_PROGNAME, 0, LOG_DAEMON);
+ syslog(LOG_NOTICE, "%s starting", argv[0]);
+
+ initialize();
+
+#ifndef DEBUG
+ dropprivs();
+
+ /* run in the background as a daemon */
+ if (daemon(0, 0)) {
+ syslog(LOG_ERR, "daemon() failed: %m");
+ exit(1);
+ }
+#endif
+
+ syslog(LOG_NOTICE, "%s initialized", argv[0]);
+ process_connections();
+
+ /* we should never get here */
+ return 1;
+}
+
diff --git a/src/mls_level.c b/src/mls_level.c
new file mode 100644
index 0000000..353ffe9
--- /dev/null
+++ b/src/mls_level.c
@@ -0,0 +1,164 @@
+#include <stdio.h>
+#include "mls_level.h"
+#include <sepol/policydb/ebitmap.h>
+
+mls_level_t *mls_level_from_string(char *mls_context)
+{
+ char delim;
+ char *scontextp, *p, *lptr;
+ mls_level_t *l = (mls_level_t *) calloc(1, sizeof(mls_level_t));
+
+ /* Extract low sensitivity. */
+ scontextp = p = mls_context;
+ while (*p && *p != ':' && *p != '-')
+ p++;
+
+ delim = *p;
+ if (delim != 0)
+ *p++ = 0;
+
+ if (*scontextp != 's')
+ goto err;
+ l->sens = atoi(scontextp + 1);
+
+ if (delim == ':') {
+ /* Extract category set. */
+ while (1) {
+ scontextp = p;
+ while (*p && *p != ',' && *p != '-')
+ p++;
+ delim = *p;
+ if (delim != 0)
+ *p++ = 0;
+
+ /* Separate into level if exists */
+ if ((lptr = strchr(scontextp, '.')) != NULL) {
+ /* Remove '.' */
+ *lptr++ = 0;
+ }
+
+ if (*scontextp != 'c')
+ goto err;
+ int bit = atoi(scontextp + 1);
+ if (ebitmap_set_bit(&l->cat, bit, 1))
+ goto err;
+
+ /* If level, set all categories in level */
+ if (lptr) {
+ if (*scontextp != 'c')
+ goto err;
+ int ubit = atoi(lptr + 1);
+ int i;
+ for (i = bit + 1; i <= ubit; i++) {
+ if (ebitmap_set_bit
+ (&l->cat, i, 1))
+ goto err;
+ }
+ }
+
+ if (delim != ',')
+ break;
+ }
+ }
+
+ return l;
+
+ err:
+ free(l);
+ return NULL;
+}
+
+/*
+ * Return the length in bytes for the MLS fields of the
+ * security context string representation of `context'.
+ */
+unsigned int mls_compute_string_len(mls_level_t *l)
+{
+ unsigned int len = 0;
+ char temp[16];
+ unsigned int i, level = 0;
+ ebitmap_node_t *cnode;
+
+ if (!l)
+ return 0;
+
+ len += snprintf(temp, sizeof(temp), "s%d", l->sens);
+
+ ebitmap_for_each_bit(&l->cat, cnode, i) {
+ if (ebitmap_node_get_bit(cnode, i)) {
+ if (level) {
+ level++;
+ continue;
+ }
+
+ len++; /* : or ,` */
+
+ len += snprintf(temp, sizeof(temp), "c%d", i);
+ level++;
+ } else {
+ if (level > 1)
+ len += snprintf(temp, sizeof(temp), ".c%d", i-1);
+ level = 0;
+ }
+ }
+
+ /* Handle case where last category is the end of level */
+ if (level > 1)
+ len += snprintf(temp, sizeof(temp), ".c%d", i-1);
+ return len;
+}
+
+char *mls_level_to_string(mls_level_t *l)
+{
+ unsigned int wrote_sep, len = mls_compute_string_len(l);
+ unsigned int i, level = 0;
+ ebitmap_node_t *cnode;
+ wrote_sep = 0;
+
+ if (len == 0)
+ return NULL;
+ char *result = (char *)malloc(len + 1);
+ char *p = result;
+
+ p += sprintf(p, "s%d", l->sens);
+
+ /* categories */
+ ebitmap_for_each_bit(&l->cat, cnode, i) {
+ if (ebitmap_node_get_bit(cnode, i)) {
+ if (level) {
+ level++;
+ continue;
+ }
+
+ if (!wrote_sep) {
+ *p++ = ':';
+ wrote_sep = 1;
+ } else
+ *p++ = ',';
+ p += sprintf(p, "c%d", i);
+ level++;
+ } else {
+ if (level > 1) {
+ if (level > 2)
+ *p++ = '.';
+ else
+ *p++ = ',';
+
+ p += sprintf(p, "c%d", i-1);
+ }
+ level = 0;
+ }
+ }
+ /* Handle case where last category is the end of level */
+ if (level > 1) {
+ if (level > 2)
+ *p++ = '.';
+ else
+ *p++ = ',';
+
+ p += sprintf(p, "c%d", i-1);
+ }
+
+ *(result + len) = 0;
+ return result;
+}
diff --git a/src/mls_level.h b/src/mls_level.h
new file mode 100644
index 0000000..52e629b
--- /dev/null
+++ b/src/mls_level.h
@@ -0,0 +1,10 @@
+#ifndef __mls_level_h__
+#define __mls_level_h__
+
+#include <sepol/policydb/mls_types.h>
+
+unsigned int mls_compute_string_len(mls_level_t *r);
+mls_level_t *mls_level_from_string(char *mls_context);
+char *mls_level_to_string(mls_level_t *r);
+
+#endif
diff --git a/test/ab.test b/test/ab.test
new file mode 100644
index 0000000..f8d36da
--- /dev/null
+++ b/test/ab.test
@@ -0,0 +1,11 @@
+Secret A==s4:c0,c200.c511
+Secret B==s4:c1,c200.c511
+Secret AB==s4:c0,c1,c200.c511
+Unclassified-Secret AB==s1-s4:c0,c1,c200.c511
+Secret AB-Secret A==s4:c0,c1,c200.c511-s4:c0,c200.c511
+Secret AB-Secret B==s4:c0,c1,c200.c511-s4:c1,c200.c511
+Secret AB-Secret==s4:c0,c1,c200.c511-s4:c200.c511
+
+# error
+Secret C==Secret C
+Secret C-Secret D==Secret C-Secret D
diff --git a/test/eyes-only-range.test b/test/eyes-only-range.test
new file mode 100644
index 0000000..120e0f5
--- /dev/null
+++ b/test/eyes-only-range.test
@@ -0,0 +1,3 @@
+Restricted FRA Eyes only-Secret==s2:c200.c273,c275.c511-s4:c200.c511
+Restricted FRA/USA Eyes only-Secret FRA Eyes only==s2:c200.c273,c275.c429,c431.c511-s4:c200.c273,c275.c511
+Secret ZWE Eyes only-Top Secret==s4:c200.c443,c445.c511-s5:c200.c511
diff --git a/test/eyes-only.test b/test/eyes-only.test
new file mode 100644
index 0000000..79b58de
--- /dev/null
+++ b/test/eyes-only.test
@@ -0,0 +1,734 @@
+# Aruba - bit 201
+Secret ABW Eyes only==s4:c200,c202.c511
+Restricted AA Eyes only=s2:c200,c202.c511
+# Afghanistan - bit 202
+Secret AFG Eyes only==s4:c200,c201,c203.c511
+Restricted AF Eyes only=s2:c200,c201,c203.c511
+# Angola - bit 203
+Secret AGO Eyes only==s4:c200.c202,c204.c511
+Restricted AO Eyes only=s2:c200.c202,c204.c511
+# Anguilla - bit 204
+Secret AIA Eyes only==s4:c200.c203,c205.c511
+Restricted AV Eyes only=s2:c200.c203,c205.c511
+# Albania - bit 205
+Secret ALB Eyes only==s4:c200.c204,c206.c511
+Restricted AL Eyes only=s2:c200.c204,c206.c511
+# Andorra - bit 206
+Secret AND Eyes only==s4:c200.c205,c207.c511
+Restricted AN Eyes only=s2:c200.c205,c207.c511
+# Netherlands Antilles - bit 207
+Secret ANT Eyes only==s4:c200.c206,c208.c511
+Restricted NT Eyes only=s2:c200.c206,c208.c511
+# United Arab Emirates - bit 208
+Secret ARE Eyes only==s4:c200.c207,c209.c511
+Restricted AE Eyes only=s2:c200.c207,c209.c511
+# Argentina - bit 209
+Secret ARG Eyes only==s4:c200.c208,c210.c511
+Restricted AR Eyes only=s2:c200.c208,c210.c511
+# Armenia - bit 210
+Secret ARM Eyes only==s4:c200.c209,c211.c511
+Restricted AM Eyes only=s2:c200.c209,c211.c511
+# American Samoa - bit 211
+Secret ASM Eyes only==s4:c200.c210,c212.c511
+Restricted AQ Eyes only=s2:c200.c210,c212.c511
+# Antarctica - bit 212
+Secret ATA Eyes only==s4:c200.c211,c213.c511
+Restricted AY Eyes only=s2:c200.c211,c213.c511
+# French Southern and Antarctic Lands - bit 213
+Secret ATF Eyes only==s4:c200.c212,c214.c511
+Restricted FS Eyes only=s2:c200.c212,c214.c511
+# Antigua and Barbuda - bit 214
+Secret ATG Eyes only==s4:c200.c213,c215.c511
+Restricted AC Eyes only=s2:c200.c213,c215.c511
+# Australia - bit 215
+Secret AUS Eyes only==s4:c200.c214,c216.c511
+Restricted AS Eyes only=s2:c200.c214,c216.c511
+# Austria - bit 216
+Secret AUT Eyes only==s4:c200.c215,c217.c511
+Restricted AU Eyes only=s2:c200.c215,c217.c511
+# Azerbaijan - bit 217
+Secret AZE Eyes only==s4:c200.c216,c218.c511
+Restricted AJ Eyes only=s2:c200.c216,c218.c511
+# Burundi - bit 218
+Secret BDI Eyes only==s4:c200.c217,c219.c511
+Restricted BY Eyes only=s2:c200.c217,c219.c511
+# Belgium - bit 219
+Secret BEL Eyes only==s4:c200.c218,c220.c511
+Restricted BE Eyes only=s2:c200.c218,c220.c511
+# Benin - bit 220
+Secret BEN Eyes only==s4:c200.c219,c221.c511
+Restricted BN Eyes only=s2:c200.c219,c221.c511
+# Burkina Faso - bit 221
+Secret BFA Eyes only==s4:c200.c220,c222.c511
+Restricted UV Eyes only=s2:c200.c220,c222.c511
+# Bangladesh - bit 222
+Secret BGD Eyes only==s4:c200.c221,c223.c511
+Restricted BG Eyes only=s2:c200.c221,c223.c511
+# Bulgaria - bit 223
+Secret BGR Eyes only==s4:c200.c222,c224.c511
+Restricted BU Eyes only=s2:c200.c222,c224.c511
+# Bahrain - bit 224
+Secret BHR Eyes only==s4:c200.c223,c225.c511
+Restricted BA Eyes only=s2:c200.c223,c225.c511
+# Bahamas, The - bit 225
+Secret BHS Eyes only==s4:c200.c224,c226.c511
+Restricted BF Eyes only=s2:c200.c224,c226.c511
+# Bosnia and Herzegovina - bit 226
+Secret BIH Eyes only==s4:c200.c225,c227.c511
+Restricted BK Eyes only=s2:c200.c225,c227.c511
+# Saint Barthelemy - bit 227
+Secret BLM Eyes only==s4:c200.c226,c228.c511
+Restricted TB Eyes only=s2:c200.c226,c228.c511
+# Belarus - bit 228
+Secret BLR Eyes only==s4:c200.c227,c229.c511
+Restricted BO Eyes only=s2:c200.c227,c229.c511
+# Belize - bit 229
+Secret BLZ Eyes only==s4:c200.c228,c230.c511
+Restricted BH Eyes only=s2:c200.c228,c230.c511
+# Bermuda - bit 230
+Secret BMU Eyes only==s4:c200.c229,c231.c511
+Restricted BD Eyes only=s2:c200.c229,c231.c511
+# Bolivia - bit 231
+Secret BOL Eyes only==s4:c200.c230,c232.c511
+Restricted BL Eyes only=s2:c200.c230,c232.c511
+# Brazil - bit 232
+Secret BRA Eyes only==s4:c200.c231,c233.c511
+Restricted BR Eyes only=s2:c200.c231,c233.c511
+# Barbados - bit 233
+Secret BRB Eyes only==s4:c200.c232,c234.c511
+Restricted BB Eyes only=s2:c200.c232,c234.c511
+# Brunei - bit 234
+Secret BRN Eyes only==s4:c200.c233,c235.c511
+Restricted BX Eyes only=s2:c200.c233,c235.c511
+# Bhutan - bit 235
+Secret BTN Eyes only==s4:c200.c234,c236.c511
+Restricted BT Eyes only=s2:c200.c234,c236.c511
+# Bouvet Island - bit 236
+Secret BVT Eyes only==s4:c200.c235,c237.c511
+Restricted BV Eyes only=s2:c200.c235,c237.c511
+# Botswana - bit 237
+Secret BWA Eyes only==s4:c200.c236,c238.c511
+Restricted BC Eyes only=s2:c200.c236,c238.c511
+# Central African Republic - bit 238
+Secret CAF Eyes only==s4:c200.c237,c239.c511
+Restricted CT Eyes only=s2:c200.c237,c239.c511
+# Canada - bit 239
+Secret CAN Eyes only==s4:c200.c238,c240.c511
+Restricted CA Eyes only=s2:c200.c238,c240.c511
+# Cocos (Keeling) Islands - bit 240 part of AUS
+Secret CCK Eyes only==s4:c200.c239,c241.c511
+Restricted CK Eyes only=s2:c200.c239,c241.c511
+# Switzerland - bit 241
+Secret CHE Eyes only==s4:c200.c240,c242.c511
+Restricted SZ Eyes only=s2:c200.c240,c242.c511
+# Chile - bit 242
+Secret CHL Eyes only==s4:c200.c241,c243.c511
+Restricted CI Eyes only=s2:c200.c241,c243.c511
+# China - bit 243
+Secret CHN Eyes only==s4:c200.c242,c244.c511
+Restricted CH Eyes only=s2:c200.c242,c244.c511
+# Cote d'Ivoire - bit 244
+Secret CIV Eyes only==s4:c200.c243,c245.c511
+Restricted IV Eyes only=s2:c200.c243,c245.c511
+# Cameroon - bit 245
+Secret CMR Eyes only==s4:c200.c244,c246.c511
+Restricted CM Eyes only=s2:c200.c244,c246.c511
+# Congo, Democratic Republic of the - bit 246
+Secret COD Eyes only==s4:c200.c245,c247.c511
+Restricted CG Eyes only=s2:c200.c245,c247.c511
+# Congo, Republic of the - bit 247
+Secret COG Eyes only==s4:c200.c246,c248.c511
+Restricted CF Eyes only=s2:c200.c246,c248.c511
+# Cook Islands - bit 248
+Secret COK Eyes only==s4:c200.c247,c249.c511
+Restricted CW Eyes only=s2:c200.c247,c249.c511
+# Colombia - bit 249
+Secret COL Eyes only==s4:c200.c248,c250.c511
+Restricted CO Eyes only=s2:c200.c248,c250.c511
+# Comoros - bit 250
+Secret COM Eyes only==s4:c200.c249,c251.c511
+Restricted CN Eyes only=s2:c200.c249,c251.c511
+# Cape Verde - bit 251
+Secret CPV Eyes only==s4:c200.c250,c252.c511
+Restricted CV Eyes only=s2:c200.c250,c252.c511
+# Costa Rica - bit 252
+Secret CRI Eyes only==s4:c200.c251,c253.c511
+Restricted CS Eyes only=s2:c200.c251,c253.c511
+# Cuba - bit 253
+Secret CUB Eyes only==s4:c200.c252,c254.c511
+Restricted CU Eyes only=s2:c200.c252,c254.c511
+# Christmas Island - bit 254
+Secret CXR Eyes only==s4:c200.c253,c255.c511
+Restricted KT Eyes only=s2:c200.c253,c255.c511
+# Cayman Islands - bit 255
+Secret CYM Eyes only==s4:c200.c254,c256.c511
+Restricted CJ Eyes only=s2:c200.c254,c256.c511
+# Cyprus - bit 256
+Secret CYP Eyes only==s4:c200.c255,c257.c511
+Restricted CY Eyes only=s2:c200.c255,c257.c511
+# Czech Republic - bit 257
+Secret CZE Eyes only==s4:c200.c256,c258.c511
+Restricted EZ Eyes only=s2:c200.c256,c258.c511
+# Germany - bit 258
+Secret DEU Eyes only==s4:c200.c257,c259.c511
+Restricted GM Eyes only=s2:c200.c257,c259.c511
+# Djibouti - bit 259
+Secret DJI Eyes only==s4:c200.c258,c260.c511
+Restricted DJ Eyes only=s2:c200.c258,c260.c511
+# Dominica - bit 260
+Secret DMA Eyes only==s4:c200.c259,c261.c511
+Restricted DO Eyes only=s2:c200.c259,c261.c511
+# Denmark - bit 261
+Secret DNK Eyes only==s4:c200.c260,c262.c511
+Restricted DA Eyes only=s2:c200.c260,c262.c511
+# Dominican Republic - bit 262
+Secret DOM Eyes only==s4:c200.c261,c263.c511
+Restricted DR Eyes only=s2:c200.c261,c263.c511
+# Algeria - bit 263
+Secret DZA Eyes only==s4:c200.c262,c264.c511
+Restricted AG Eyes only=s2:c200.c262,c264.c511
+# Ecuador - bit 264
+Secret ECU Eyes only==s4:c200.c263,c265.c511
+Restricted EC Eyes only=s2:c200.c263,c265.c511
+# Egypt - bit 265
+Secret EGY Eyes only==s4:c200.c264,c266.c511
+Restricted EG Eyes only=s2:c200.c264,c266.c511
+# Eritrea - bit 266
+Secret ERI Eyes only==s4:c200.c265,c267.c511
+Restricted ER Eyes only=s2:c200.c265,c267.c511
+# Western Sahara - bit 267
+Secret ESH Eyes only==s4:c200.c266,c268.c511
+Restricted WI Eyes only=s2:c200.c266,c268.c511
+# Spain - bit 268
+Secret ESP Eyes only==s4:c200.c267,c269.c511
+Restricted SP Eyes only=s2:c200.c267,c269.c511
+# Estonia - bit 269
+Secret EST Eyes only==s4:c200.c268,c270.c511
+Restricted EN Eyes only=s2:c200.c268,c270.c511
+# Ethiopia - bit 270
+Secret ETH Eyes only==s4:c200.c269,c271.c511
+Restricted ET Eyes only=s2:c200.c269,c271.c511
+# Finland - bit 271
+Secret FIN Eyes only==s4:c200.c270,c272.c511
+Restricted FI Eyes only=s2:c200.c270,c272.c511
+# Fiji - bit 272
+Secret FJI Eyes only==s4:c200.c271,c273.c511
+Restricted FJ Eyes only=s2:c200.c271,c273.c511
+# Falkland Islands (Islas Malvinas) - bit 273
+Secret FLK Eyes only==s4:c200.c272,c274.c511
+Restricted FK Eyes only=s2:c200.c272,c274.c511
+# France - bit 274
+Secret FRA Eyes only==s4:c200.c273,c275.c511
+Restricted FR Eyes only=s2:c200.c273,c275.c511
+# Faroe Islands - bit 275
+Secret FRO Eyes only==s4:c200.c274,c276.c511
+Restricted FO Eyes only=s2:c200.c274,c276.c511
+# Micronesia, Federated States of - bit 276
+Secret FSM Eyes only==s4:c200.c275,c277.c511
+Restricted FM Eyes only=s2:c200.c275,c277.c511
+# Gabon - bit 277
+Secret GAB Eyes only==s4:c200.c276,c278.c511
+Restricted GB Eyes only=s2:c200.c276,c278.c511
+# United Kingdom - bit 278
+Secret GBR Eyes only==s4:c200.c277,c279.c511
+Restricted UK Eyes only=s2:c200.c277,c279.c511
+# Georgia - bit 279
+Secret GEO Eyes only==s4:c200.c278,c280.c511
+Restricted GG Eyes only=s2:c200.c278,c280.c511
+# Guernsey - bit 280 part of UK
+Secret GGY Eyes only==s4:c200.c279,c281.c511
+Restricted GK Eyes only=s2:c200.c279,c281.c511
+# Ghana - bit 281
+Secret GHA Eyes only==s4:c200.c280,c282.c511
+Restricted GH Eyes only=s2:c200.c280,c282.c511
+# Gibraltar - bit 282
+Secret GIB Eyes only==s4:c200.c281,c283.c511
+Restricted GI Eyes only=s2:c200.c281,c283.c511
+# Guinea - bit 283
+Secret GIN Eyes only==s4:c200.c282,c284.c511
+Restricted GV Eyes only=s2:c200.c282,c284.c511
+# Guadeloupe - bit 284
+Secret GLP Eyes only==s4:c200.c283,c285.c511
+Restricted GP Eyes only=s2:c200.c283,c285.c511
+# Gambia, The - bit 285
+Secret GMB Eyes only==s4:c200.c284,c286.c511
+Restricted GA Eyes only=s2:c200.c284,c286.c511
+# Guinea-Bissau - bit 286
+Secret GNB Eyes only==s4:c200.c285,c287.c511
+Restricted PU Eyes only=s2:c200.c285,c287.c511
+# Equatorial Guinea - bit 287
+Secret GNQ Eyes only==s4:c200.c286,c288.c511
+Restricted EK Eyes only=s2:c200.c286,c288.c511
+# Greece - bit 288
+Secret GRC Eyes only==s4:c200.c287,c289.c511
+Restricted GR Eyes only=s2:c200.c287,c289.c511
+# Grenada - bit 289
+Secret GRD Eyes only==s4:c200.c288,c290.c511
+Restricted GJ Eyes only=s2:c200.c288,c290.c511
+# Greenland - bit 290
+Secret GRL Eyes only==s4:c200.c289,c291.c511
+Restricted GL Eyes only=s2:c200.c289,c291.c511
+# Guatemala - bit 291
+Secret GTM Eyes only==s4:c200.c290,c292.c511
+Restricted GT Eyes only=s2:c200.c290,c292.c511
+# French Guiana - bit 292
+Secret GUF Eyes only==s4:c200.c291,c293.c511
+Restricted FG Eyes only=s2:c200.c291,c293.c511
+# Guam - bit 293
+Secret GUM Eyes only==s4:c200.c292,c294.c511
+Restricted GQ Eyes only=s2:c200.c292,c294.c511
+# Guyana - bit 294
+Secret GUY Eyes only==s4:c200.c293,c295.c511
+Restricted GY Eyes only=s2:c200.c293,c295.c511
+# Hong Kong - bit 295
+Secret HKG Eyes only==s4:c200.c294,c296.c511
+Restricted HK Eyes only=s2:c200.c294,c296.c511
+# Heard Island and McDonald Islands - bit 296
+Secret HMD Eyes only==s4:c200.c295,c297.c511
+Restricted HM Eyes only=s2:c200.c295,c297.c511
+# Honduras - bit 297
+Secret HND Eyes only==s4:c200.c296,c298.c511
+Restricted HO Eyes only=s2:c200.c296,c298.c511
+# Croatia - bit 298
+Secret HRV Eyes only==s4:c200.c297,c299.c511
+Restricted HR Eyes only=s2:c200.c297,c299.c511
+# Haiti - bit 299
+Secret HTI Eyes only==s4:c200.c298,c300.c511
+Restricted HA Eyes only=s2:c200.c298,c300.c511
+# Hungary - bit 300
+Secret HUN Eyes only==s4:c200.c299,c301.c511
+Restricted HU Eyes only=s2:c200.c299,c301.c511
+# Indonesia - bit 301
+Secret IDN Eyes only==s4:c200.c300,c302.c511
+Restricted ID Eyes only=s2:c200.c300,c302.c511
+# Isle of Man - bit 302 part of UK
+Secret IMN Eyes only==s4:c200.c301,c303.c511
+Restricted IM Eyes only=s2:c200.c301,c303.c511
+# India - bit 303
+Secret IND Eyes only==s4:c200.c302,c304.c511
+Restricted IN Eyes only=s2:c200.c302,c304.c511
+# British Indian Ocean Territory - bit 304
+Secret IOT Eyes only==s4:c200.c303,c305.c511
+Restricted IO Eyes only=s2:c200.c303,c305.c511
+# Ireland - bit 305
+Secret IRL Eyes only==s4:c200.c304,c306.c511
+Restricted EI Eyes only=s2:c200.c304,c306.c511
+# Iran - bit 306
+Secret IRN Eyes only==s4:c200.c305,c307.c511
+Restricted IR Eyes only=s2:c200.c305,c307.c511
+# Iraq - bit 307
+Secret IRQ Eyes only==s4:c200.c306,c308.c511
+Restricted IZ Eyes only=s2:c200.c306,c308.c511
+# Iceland - bit 308
+Secret ISL Eyes only==s4:c200.c307,c309.c511
+Restricted IC Eyes only=s2:c200.c307,c309.c511
+# Israel - bit 309
+Secret ISR Eyes only==s4:c200.c308,c310.c511
+Restricted IS Eyes only=s2:c200.c308,c310.c511
+# Italy - bit 310
+Secret ITA Eyes only==s4:c200.c309,c311.c511
+Restricted IT Eyes only=s2:c200.c309,c311.c511
+# Jamaica - bit 311
+Secret JAM Eyes only==s4:c200.c310,c312.c511
+Restricted JM Eyes only=s2:c200.c310,c312.c511
+# Jersey - bit 312 part of UK
+Secret JEY Eyes only==s4:c200.c311,c313.c511
+Restricted JE Eyes only=s2:c200.c311,c313.c511
+# Jordan - bit 313
+Secret JOR Eyes only==s4:c200.c312,c314.c511
+Restricted JO Eyes only=s2:c200.c312,c314.c511
+# Japan - bit 314
+Secret JPN Eyes only==s4:c200.c313,c315.c511
+Restricted JA Eyes only=s2:c200.c313,c315.c511
+# Kazakhstan - bit 315
+Secret KAZ Eyes only==s4:c200.c314,c316.c511
+Restricted KZ Eyes only=s2:c200.c314,c316.c511
+# Kenya - bit 316
+Secret KEN Eyes only==s4:c200.c315,c317.c511
+Restricted KE Eyes only=s2:c200.c315,c317.c511
+# Kyrgyzstan - bit 317
+Secret KGZ Eyes only==s4:c200.c316,c318.c511
+Restricted KG Eyes only=s2:c200.c316,c318.c511
+# Cambodia - bit 318
+Secret KHM Eyes only==s4:c200.c317,c319.c511
+Restricted CB Eyes only=s2:c200.c317,c319.c511
+# Kiribati - bit 319
+Secret KIR Eyes only==s4:c200.c318,c320.c511
+Restricted KR Eyes only=s2:c200.c318,c320.c511
+# Saint Kitts and Nevis - bit 320
+Secret KNA Eyes only==s4:c200.c319,c321.c511
+Restricted SC Eyes only=s2:c200.c319,c321.c511
+# Korea, South - bit 321
+Secret KOR Eyes only==s4:c200.c320,c322.c511
+Restricted KS Eyes only=s2:c200.c320,c322.c511
+# Kuwait - bit 322
+Secret KWT Eyes only==s4:c200.c321,c323.c511
+Restricted KU Eyes only=s2:c200.c321,c323.c511
+# Laos - bit 323
+Secret LAO Eyes only==s4:c200.c322,c324.c511
+Restricted LA Eyes only=s2:c200.c322,c324.c511
+# Lebanon - bit 324
+Secret LBN Eyes only==s4:c200.c323,c325.c511
+Restricted LE Eyes only=s2:c200.c323,c325.c511
+# Liberia - bit 325
+Secret LBR Eyes only==s4:c200.c324,c326.c511
+Restricted LI Eyes only=s2:c200.c324,c326.c511
+# Libya - bit 326
+Secret LBY Eyes only==s4:c200.c325,c327.c511
+Restricted LY Eyes only=s2:c200.c325,c327.c511
+# Saint Lucia - bit 327
+Secret LCA Eyes only==s4:c200.c326,c328.c511
+Restricted ST Eyes only=s2:c200.c326,c328.c511
+# Liechtenstein - bit 328
+Secret LIE Eyes only==s4:c200.c327,c329.c511
+Restricted LS Eyes only=s2:c200.c327,c329.c511
+# Sri Lanka - bit 329
+Secret LKA Eyes only==s4:c200.c328,c330.c511
+Restricted CE Eyes only=s2:c200.c328,c330.c511
+# Lesotho - bit 330
+Secret LSO Eyes only==s4:c200.c329,c331.c511
+Restricted LT Eyes only=s2:c200.c329,c331.c511
+# Lithuania - bit 331
+Secret LTU Eyes only==s4:c200.c330,c332.c511
+Restricted LH Eyes only=s2:c200.c330,c332.c511
+# Luxembourg - bit 332
+Secret LUX Eyes only==s4:c200.c331,c333.c511
+Restricted LU Eyes only=s2:c200.c331,c333.c511
+# Latvia - bit 333
+Secret LVA Eyes only==s4:c200.c332,c334.c511
+Restricted LG Eyes only=s2:c200.c332,c334.c511
+# Macau - bit 334
+Secret MAC Eyes only==s4:c200.c333,c335.c511
+Restricted MC Eyes only=s2:c200.c333,c335.c511
+# Saint Martin - bit 335
+Secret MAF Eyes only==s4:c200.c334,c336.c511
+Restricted RN Eyes only=s2:c200.c334,c336.c511
+# Morocco - bit 336
+Secret MAR Eyes only==s4:c200.c335,c337.c511
+Restricted MO Eyes only=s2:c200.c335,c337.c511
+# Monaco - bit 337
+Secret MCO Eyes only==s4:c200.c336,c338.c511
+Restricted MN Eyes only=s2:c200.c336,c338.c511
+# Moldova - bit 338
+Secret MDA Eyes only==s4:c200.c337,c339.c511
+Restricted MD Eyes only=s2:c200.c337,c339.c511
+# Madagascar - bit 339
+Secret MDG Eyes only==s4:c200.c338,c340.c511
+Restricted MA Eyes only=s2:c200.c338,c340.c511
+# Maldives - bit 340
+Secret MDV Eyes only==s4:c200.c339,c341.c511
+Restricted MV Eyes only=s2:c200.c339,c341.c511
+# Mexico - bit 341
+Secret MEX Eyes only==s4:c200.c340,c342.c511
+Restricted MX Eyes only=s2:c200.c340,c342.c511
+# Marshall Islands - bit 342
+Secret MHL Eyes only==s4:c200.c341,c343.c511
+Restricted RM Eyes only=s2:c200.c341,c343.c511
+# Macedonia - bit 343 part of FYR
+Secret MKD Eyes only==s4:c200.c342,c344.c511
+Restricted MK Eyes only=s2:c200.c342,c344.c511
+# Mali - bit 344
+Secret MLI Eyes only==s4:c200.c343,c345.c511
+Restricted ML Eyes only=s2:c200.c343,c345.c511
+# Malta - bit 345
+Secret MLT Eyes only==s4:c200.c344,c346.c511
+Restricted MT Eyes only=s2:c200.c344,c346.c511
+# Burma - bit 346
+Secret MMR Eyes only==s4:c200.c345,c347.c511
+Restricted BM Eyes only=s2:c200.c345,c347.c511
+# Montenegro - bit 347
+Secret MNE Eyes only==s4:c200.c346,c348.c511
+Restricted MJ Eyes only=s2:c200.c346,c348.c511
+# Mongolia - bit 348
+Secret MNG Eyes only==s4:c200.c347,c349.c511
+Restricted MG Eyes only=s2:c200.c347,c349.c511
+# Northern Mariana Islands - bit 349
+Secret MNP Eyes only==s4:c200.c348,c350.c511
+Restricted CQ Eyes only=s2:c200.c348,c350.c511
+# Mozambique - bit 350
+Secret MOZ Eyes only==s4:c200.c349,c351.c511
+Restricted MZ Eyes only=s2:c200.c349,c351.c511
+# Mauritania - bit 351
+Secret MRT Eyes only==s4:c200.c350,c352.c511
+Restricted MR Eyes only=s2:c200.c350,c352.c511
+# Montserrat - bit 352
+Secret MSR Eyes only==s4:c200.c351,c353.c511
+Restricted MH Eyes only=s2:c200.c351,c353.c511
+# Martinique - bit 353
+Secret MTQ Eyes only==s4:c200.c352,c354.c511
+Restricted MB Eyes only=s2:c200.c352,c354.c511
+# Mauritius - bit 354
+Secret MUS Eyes only==s4:c200.c353,c355.c511
+Restricted MP Eyes only=s2:c200.c353,c355.c511
+# Malawi - bit 355
+Secret MWI Eyes only==s4:c200.c354,c356.c511
+Restricted MI Eyes only=s2:c200.c354,c356.c511
+# Malaysia - bit 356
+Secret MYS Eyes only==s4:c200.c355,c357.c511
+Restricted MY Eyes only=s2:c200.c355,c357.c511
+# Mayotte - bit 357 part of FRA
+Secret MYT Eyes only==s4:c200.c356,c358.c511
+Restricted MF Eyes only=s2:c200.c356,c358.c511
+# Namibia - bit 358
+Secret NAM Eyes only==s4:c200.c357,c359.c511
+Restricted WA Eyes only=s2:c200.c357,c359.c511
+# New Caledonia - bit 359
+Secret NCL Eyes only==s4:c200.c358,c360.c511
+Restricted NC Eyes only=s2:c200.c358,c360.c511
+# Niger - bit 360
+Secret NER Eyes only==s4:c200.c359,c361.c511
+Restricted NG Eyes only=s2:c200.c359,c361.c511
+# Norfolk Island - bit 361
+Secret NFK Eyes only==s4:c200.c360,c362.c511
+Restricted NF Eyes only=s2:c200.c360,c362.c511
+# Nigeria - bit 362
+Secret NGA Eyes only==s4:c200.c361,c363.c511
+Restricted NI Eyes only=s2:c200.c361,c363.c511
+# Nicaragua - bit 363
+Secret NIC Eyes only==s4:c200.c362,c364.c511
+Restricted NU Eyes only=s2:c200.c362,c364.c511
+# Niue - bit 364
+Secret NIU Eyes only==s4:c200.c363,c365.c511
+Restricted NE Eyes only=s2:c200.c363,c365.c511
+# Netherlands - bit 365
+Secret NLD Eyes only==s4:c200.c364,c366.c511
+Restricted NL Eyes only=s2:c200.c364,c366.c511
+# Norway - bit 366
+Secret NOR Eyes only==s4:c200.c365,c367.c511
+Restricted NO Eyes only=s2:c200.c365,c367.c511
+# Nepal - bit 367
+Secret NPL Eyes only==s4:c200.c366,c368.c511
+Restricted NP Eyes only=s2:c200.c366,c368.c511
+# Nauru - bit 368
+Secret NRU Eyes only==s4:c200.c367,c369.c511
+Restricted NR Eyes only=s2:c200.c367,c369.c511
+# New Zealand - bit 369
+Secret NZL Eyes only==s4:c200.c368,c370.c511
+Restricted NZ Eyes only=s2:c200.c368,c370.c511
+# Oman - bit 370
+Secret OMN Eyes only==s4:c200.c369,c371.c511
+Restricted MU Eyes only=s2:c200.c369,c371.c511
+# Pakistan - bit 371
+Secret PAK Eyes only==s4:c200.c370,c372.c511
+Restricted PK Eyes only=s2:c200.c370,c372.c511
+# Panama - bit 372
+Secret PAN Eyes only==s4:c200.c371,c373.c511
+Restricted PM Eyes only=s2:c200.c371,c373.c511
+# Pitcairn Islands - bit 373
+Secret PCN Eyes only==s4:c200.c372,c374.c511
+Restricted PC Eyes only=s2:c200.c372,c374.c511
+# Peru - bit 374
+Secret PER Eyes only==s4:c200.c373,c375.c511
+Restricted PE Eyes only=s2:c200.c373,c375.c511
+# Philippines - bit 375
+Secret PHL Eyes only==s4:c200.c374,c376.c511
+Restricted RP Eyes only=s2:c200.c374,c376.c511
+# Palau - bit 376
+Secret PLW Eyes only==s4:c200.c375,c377.c511
+Restricted PS Eyes only=s2:c200.c375,c377.c511
+# Papua New Guinea - bit 377
+Secret PNG Eyes only==s4:c200.c376,c378.c511
+Restricted PP Eyes only=s2:c200.c376,c378.c511
+# Poland - bit 378
+Secret POL Eyes only==s4:c200.c377,c379.c511
+Restricted PL Eyes only=s2:c200.c377,c379.c511
+# Puerto Rico - bit 379
+Secret PRI Eyes only==s4:c200.c378,c380.c511
+Restricted RQ Eyes only=s2:c200.c378,c380.c511
+# Korea, North - bit 380
+Secret PRK Eyes only==s4:c200.c379,c381.c511
+Restricted KN Eyes only=s2:c200.c379,c381.c511
+# Portugal - bit 381
+Secret PRT Eyes only==s4:c200.c380,c382.c511
+Restricted PO Eyes only=s2:c200.c380,c382.c511
+# Paraguay - bit 382
+Secret PRY Eyes only==s4:c200.c381,c383.c511
+Restricted PA Eyes only=s2:c200.c381,c383.c511
+# Gaza Strip - bit 383
+Secret PSE Eyes only==s4:c200.c382,c384.c511
+Restricted GZ Eyes only=s2:c200.c382,c384.c511
+# West Bank - bit 383
+Restricted WE Eyes only=s2:c200.c382,c384.c511
+# French Polynesia - bit 384
+Secret PYF Eyes only==s4:c200.c383,c385.c511
+Restricted FP Eyes only=s2:c200.c383,c385.c511
+# Qatar - bit 385
+Secret QAT Eyes only==s4:c200.c384,c386.c511
+Restricted QA Eyes only=s2:c200.c384,c386.c511
+# Reunion - bit 386
+Secret REU Eyes only==s4:c200.c385,c387.c511
+Restricted RE Eyes only=s2:c200.c385,c387.c511
+# Romania - bit 387
+Secret ROU Eyes only==s4:c200.c386,c388.c511
+Restricted RO Eyes only=s2:c200.c386,c388.c511
+# Russia - bit 388
+Secret RUS Eyes only==s4:c200.c387,c389.c511
+Restricted RS Eyes only=s2:c200.c387,c389.c511
+# Rwanda - bit 389
+Secret RWA Eyes only==s4:c200.c388,c390.c511
+Restricted RW Eyes only=s2:c200.c388,c390.c511
+# Saudi Arabia - bit 390
+Secret SAU Eyes only==s4:c200.c389,c391.c511
+Restricted SA Eyes only=s2:c200.c389,c391.c511
+# Sudan - bit 391
+Secret SDN Eyes only==s4:c200.c390,c392.c511
+Restricted SU Eyes only=s2:c200.c390,c392.c511
+# Senegal - bit 392
+Secret SEN Eyes only==s4:c200.c391,c393.c511
+Restricted SG Eyes only=s2:c200.c391,c393.c511
+# Singapore - bit 393
+Secret SGP Eyes only==s4:c200.c392,c394.c511
+Restricted SN Eyes only=s2:c200.c392,c394.c511
+# South Georgia and the Islands - bit 394
+Secret SGS Eyes only==s4:c200.c393,c395.c511
+Restricted SX Eyes only=s2:c200.c393,c395.c511
+# Saint Helena - bit 395
+Secret SHN Eyes only==s4:c200.c394,c396.c511
+Restricted SH Eyes only=s2:c200.c394,c396.c511
+# Svalbard - bit 396
+Secret SJM Eyes only==s4:c200.c395,c397.c511
+Restricted SV Eyes only=s2:c200.c395,c397.c511
+# Solomon Islands - bit 397
+Secret SLB Eyes only==s4:c200.c396,c398.c511
+Restricted BP Eyes only=s2:c200.c396,c398.c511
+# Sierra Leone - bit 398
+Secret SLE Eyes only==s4:c200.c397,c399.c511
+Restricted SL Eyes only=s2:c200.c397,c399.c511
+# El Salvador - bit 399
+Secret SLV Eyes only==s4:c200.c398,c400.c511
+Restricted ES Eyes only=s2:c200.c398,c400.c511
+# San Marino - bit 400
+Secret SMR Eyes only==s4:c200.c399,c401.c511
+Restricted SM Eyes only=s2:c200.c399,c401.c511
+# Somalia - bit 401
+Secret SOM Eyes only==s4:c200.c400,c402.c511
+Restricted SO Eyes only=s2:c200.c400,c402.c511
+# Saint Pierre and Miquelon - bit 402
+Secret SPM Eyes only==s4:c200.c401,c403.c511
+Restricted SB Eyes only=s2:c200.c401,c403.c511
+# Serbia - bit 403
+Secret SRB Eyes only==s4:c200.c402,c404.c511
+Restricted RB Eyes only=s2:c200.c402,c404.c511
+# Sao Tome and Principe - bit 404
+Secret STP Eyes only==s4:c200.c403,c405.c511
+Restricted TP Eyes only=s2:c200.c403,c405.c511
+# Suriname - bit 405
+Secret SUR Eyes only==s4:c200.c404,c406.c511
+Restricted NS Eyes only=s2:c200.c404,c406.c511
+# Slovakia - bit 406
+Secret SVK Eyes only==s4:c200.c405,c407.c511
+Restricted LO Eyes only=s2:c200.c405,c407.c511
+# Slovenia - bit 407
+Secret SVN Eyes only==s4:c200.c406,c408.c511
+Restricted SI Eyes only=s2:c200.c406,c408.c511
+# Sweden - bit 408
+Secret SWE Eyes only==s4:c200.c407,c409.c511
+Restricted SW Eyes only=s2:c200.c407,c409.c511
+# Swaziland - bit 409
+Secret SWZ Eyes only==s4:c200.c408,c410.c511
+Restricted WZ Eyes only=s2:c200.c408,c410.c511
+# Seychelles - bit 410
+Secret SYC Eyes only==s4:c200.c409,c411.c511
+Restricted SE Eyes only=s2:c200.c409,c411.c511
+# Syria - bit 411
+Secret SYR Eyes only==s4:c200.c410,c412.c511
+Restricted SY Eyes only=s2:c200.c410,c412.c511
+# Turks and Caicos Islands - bit 412
+Secret TCA Eyes only==s4:c200.c411,c413.c511
+Restricted TK Eyes only=s2:c200.c411,c413.c511
+# Chad - bit 413
+Secret TCD Eyes only==s4:c200.c412,c414.c511
+Restricted CD Eyes only=s2:c200.c412,c414.c511
+# Togo - bit 414
+Secret TGO Eyes only==s4:c200.c413,c415.c511
+Restricted TO Eyes only=s2:c200.c413,c415.c511
+# Thailand - bit 415
+Secret THA Eyes only==s4:c200.c414,c416.c511
+Restricted TH Eyes only=s2:c200.c414,c416.c511
+# Tajikistan - bit 416
+Secret TJK Eyes only==s4:c200.c415,c417.c511
+Restricted TI Eyes only=s2:c200.c415,c417.c511
+# Tokelau - bit 417
+Secret TKL Eyes only==s4:c200.c416,c418.c511
+Restricted TL Eyes only=s2:c200.c416,c418.c511
+# Turkmenistan - bit 418
+Secret TKM Eyes only==s4:c200.c417,c419.c511
+Restricted TX Eyes only=s2:c200.c417,c419.c511
+# Timor-Leste - bit 419
+Secret TLS Eyes only==s4:c200.c418,c420.c511
+Restricted TT Eyes only=s2:c200.c418,c420.c511
+# Tonga - bit 420
+Secret TON Eyes only==s4:c200.c419,c421.c511
+Restricted TN Eyes only=s2:c200.c419,c421.c511
+# Trinidad and Tobago - bit 421
+Secret TTO Eyes only==s4:c200.c420,c422.c511
+Restricted TD Eyes only=s2:c200.c420,c422.c511
+# Tunisia - bit 422
+Secret TUN Eyes only==s4:c200.c421,c423.c511
+Restricted TS Eyes only=s2:c200.c421,c423.c511
+# Turkey - bit 423
+Secret TUR Eyes only==s4:c200.c422,c424.c511
+Restricted TU Eyes only=s2:c200.c422,c424.c511
+# Tuvalu - bit 424
+Secret TUV Eyes only==s4:c200.c423,c425.c511
+Restricted TV Eyes only=s2:c200.c423,c425.c511
+# Taiwan - bit 425
+Secret TWN Eyes only==s4:c200.c424,c426.c511
+Restricted TW Eyes only=s2:c200.c424,c426.c511
+# Tanzania - bit 426
+Secret TZA Eyes only==s4:c200.c425,c427.c511
+Restricted TZ Eyes only=s2:c200.c425,c427.c511
+# Uganda - bit 427
+Secret UGA Eyes only==s4:c200.c426,c428.c511
+Restricted UG Eyes only=s2:c200.c426,c428.c511
+# Ukraine - bit 428
+Secret UKR Eyes only==s4:c200.c427,c429.c511
+Restricted UP Eyes only=s2:c200.c427,c429.c511
+# Uruguay - bit 429
+Secret URY Eyes only==s4:c200.c428,c430.c511
+Restricted UY Eyes only=s2:c200.c428,c430.c511
+# United States - bit 430
+Secret USA Eyes only==s4:c200.c429,c431.c511
+Restricted US Eyes only=s2:c200.c429,c431.c511
+# Uzbekistan - bit 431
+Secret UZB Eyes only==s4:c200.c430,c432.c511
+Restricted UZ Eyes only=s2:c200.c430,c432.c511
+# Holy See (Vatican City) - bit 432
+Secret VAT Eyes only==s4:c200.c431,c433.c511
+Restricted VT Eyes only=s2:c200.c431,c433.c511
+# Saint Vincent and the Grenadines - bit 433
+Secret VCT Eyes only==s4:c200.c432,c434.c511
+Restricted VC Eyes only=s2:c200.c432,c434.c511
+# Venezuela - bit 434
+Secret VEN Eyes only==s4:c200.c433,c435.c511
+Restricted VE Eyes only=s2:c200.c433,c435.c511
+# British Virgin Islands - bit 435
+Secret VGB Eyes only==s4:c200.c434,c436.c511
+Restricted VI Eyes only=s2:c200.c434,c436.c511
+# Virgin Islands - bit 436
+Secret VIR Eyes only==s4:c200.c435,c437.c511
+Restricted VQ Eyes only=s2:c200.c435,c437.c511
+# Vietnam - bit 437
+Secret VNM Eyes only==s4:c200.c436,c438.c511
+Restricted VM Eyes only=s2:c200.c436,c438.c511
+# Vanuatu - bit 438
+Secret VUT Eyes only==s4:c200.c437,c439.c511
+Restricted NH Eyes only=s2:c200.c437,c439.c511
+# Wallis and Futuna - bit 439
+Secret WLF Eyes only==s4:c200.c438,c440.c511
+Restricted WF Eyes only=s2:c200.c438,c440.c511
+# Samoa - bit 440
+Secret WSM Eyes only==s4:c200.c439,c441.c511
+Restricted WS Eyes only=s2:c200.c439,c441.c511
+# Yemen - bit 441
+Secret YEM Eyes only==s4:c200.c440,c442.c511
+Restricted YM Eyes only=s2:c200.c440,c442.c511
+# South Africa - bit 442
+Secret ZAF Eyes only==s4:c200.c441,c443.c511
+Restricted SF Eyes only=s2:c200.c441,c443.c511
+# Zambia - bit 443
+Secret ZMB Eyes only==s4:c200.c442,c444.c511
+Restricted ZA Eyes only=s2:c200.c442,c444.c511
+# Zimbabwe - bit 444
+Secret ZWE Eyes only==s4:c200.c443,c445.c511
+Restricted ZI Eyes only=s2:c200.c443,c445.c511
diff --git a/test/mixed.test b/test/mixed.test
new file mode 100644
index 0000000..26b1a1f
--- /dev/null
+++ b/test/mixed.test
@@ -0,0 +1,5 @@
+Secret AB Releasable to ABW==s4:c0,c1,c202.c511
+Secret A Releasable to USA==s4:c0,c201.c429,c431.c511
+Secret B Releasable to FRA==s4:c1,c201.c273,c275.c511
+Secret Releasable to FRA A=s4:c0,c201.c273,c275.c511
+
diff --git a/test/pipes.test b/test/pipes.test
new file mode 100644
index 0000000..e5ea669
--- /dev/null
+++ b/test/pipes.test
@@ -0,0 +1,6 @@
+Restricted Handle Via Iron Pipes Only==s2:c102,c200.c511
+Restricted Handle Via Copper Pipes Only==s2:c103,c200.c511
+Restricted Handle Via Plastic Pipes Only==s2:c101,c200.c511
+Restricted Handle Via Galvanized Pipes Only==s2:c104,c200.c511
+Restricted Handle Via Plastic,Iron,Copper Pipes Only==s2:c101.c103,c200.c511
+Restricted Handle Via Iron,Plastic,Copper Pipes Only=s2:c101.c103,c200.c511
diff --git a/test/rel-range.test b/test/rel-range.test
new file mode 100644
index 0000000..1623ff3
--- /dev/null
+++ b/test/rel-range.test
@@ -0,0 +1,4 @@
+Secret Releasable to ABW-Secret==s4:c202.c511-s4:c200.c511
+Confidential Rel AV-Secret=s3:c201.c203,c205.c511-s4:c200.c511
+Confidential Rel AA/AV-Secret=s3:c202,c203,c205.c511-s4:c200.c511
+Confidential Releasable to ABW/AIA/ZWE-Secret Releasable to ABW==s3:c202,c203,c205.c443,c445.c511-s4:c202.c511
diff --git a/test/rel.test b/test/rel.test
new file mode 100644
index 0000000..7dc6443
--- /dev/null
+++ b/test/rel.test
@@ -0,0 +1,734 @@
+# Aruba - bit 201
+Secret Releasable to ABW==s4:c202.c511
+Confidential Rel AA=s3:c202.c511
+# Afghanistan - bit 202
+Secret Releasable to AFG==s4:c201,c203.c511
+Confidential Rel AF=s3:c201,c203.c511
+# Angola - bit 203
+Secret Releasable to AGO==s4:c201,c202,c204.c511
+Confidential Rel AO=s3:c201,c202,c204.c511
+# Anguilla - bit 204
+Secret Releasable to AIA==s4:c201.c203,c205.c511
+Confidential Rel AV=s3:c201.c203,c205.c511
+# Albania - bit 205
+Secret Releasable to ALB==s4:c201.c204,c206.c511
+Confidential Rel AL=s3:c201.c204,c206.c511
+# Andorra - bit 206
+Secret Releasable to AND==s4:c201.c205,c207.c511
+Confidential Rel AN=s3:c201.c205,c207.c511
+# Netherlands Antilles - bit 207
+Secret Releasable to ANT==s4:c201.c206,c208.c511
+Confidential Rel NT=s3:c201.c206,c208.c511
+# United Arab Emirates - bit 208
+Secret Releasable to ARE==s4:c201.c207,c209.c511
+Confidential Rel AE=s3:c201.c207,c209.c511
+# Argentina - bit 209
+Secret Releasable to ARG==s4:c201.c208,c210.c511
+Confidential Rel AR=s3:c201.c208,c210.c511
+# Armenia - bit 210
+Secret Releasable to ARM==s4:c201.c209,c211.c511
+Confidential Rel AM=s3:c201.c209,c211.c511
+# American Samoa - bit 211
+Secret Releasable to ASM==s4:c201.c210,c212.c511
+Confidential Rel AQ=s3:c201.c210,c212.c511
+# Antarctica - bit 212
+Secret Releasable to ATA==s4:c201.c211,c213.c511
+Confidential Rel AY=s3:c201.c211,c213.c511
+# French Southern and Antarctic Lands - bit 213
+Secret Releasable to ATF==s4:c201.c212,c214.c511
+Confidential Rel FS=s3:c201.c212,c214.c511
+# Antigua and Barbuda - bit 214
+Secret Releasable to ATG==s4:c201.c213,c215.c511
+Confidential Rel AC=s3:c201.c213,c215.c511
+# Australia - bit 215
+Secret Releasable to AUS==s4:c201.c214,c216.c511
+Confidential Rel AS=s3:c201.c214,c216.c511
+# Austria - bit 216
+Secret Releasable to AUT==s4:c201.c215,c217.c511
+Confidential Rel AU=s3:c201.c215,c217.c511
+# Azerbaijan - bit 217
+Secret Releasable to AZE==s4:c201.c216,c218.c511
+Confidential Rel AJ=s3:c201.c216,c218.c511
+# Burundi - bit 218
+Secret Releasable to BDI==s4:c201.c217,c219.c511
+Confidential Rel BY=s3:c201.c217,c219.c511
+# Belgium - bit 219
+Secret Releasable to BEL==s4:c201.c218,c220.c511
+Confidential Rel BE=s3:c201.c218,c220.c511
+# Benin - bit 220
+Secret Releasable to BEN==s4:c201.c219,c221.c511
+Confidential Rel BN=s3:c201.c219,c221.c511
+# Burkina Faso - bit 221
+Secret Releasable to BFA==s4:c201.c220,c222.c511
+Confidential Rel UV=s3:c201.c220,c222.c511
+# Bangladesh - bit 222
+Secret Releasable to BGD==s4:c201.c221,c223.c511
+Confidential Rel BG=s3:c201.c221,c223.c511
+# Bulgaria - bit 223
+Secret Releasable to BGR==s4:c201.c222,c224.c511
+Confidential Rel BU=s3:c201.c222,c224.c511
+# Bahrain - bit 224
+Secret Releasable to BHR==s4:c201.c223,c225.c511
+Confidential Rel BA=s3:c201.c223,c225.c511
+# Bahamas, The - bit 225
+Secret Releasable to BHS==s4:c201.c224,c226.c511
+Confidential Rel BF=s3:c201.c224,c226.c511
+# Bosnia and Herzegovina - bit 226
+Secret Releasable to BIH==s4:c201.c225,c227.c511
+Confidential Rel BK=s3:c201.c225,c227.c511
+# Saint Barthelemy - bit 227
+Secret Releasable to BLM==s4:c201.c226,c228.c511
+Confidential Rel TB=s3:c201.c226,c228.c511
+# Belarus - bit 228
+Secret Releasable to BLR==s4:c201.c227,c229.c511
+Confidential Rel BO=s3:c201.c227,c229.c511
+# Belize - bit 229
+Secret Releasable to BLZ==s4:c201.c228,c230.c511
+Confidential Rel BH=s3:c201.c228,c230.c511
+# Bermuda - bit 230
+Secret Releasable to BMU==s4:c201.c229,c231.c511
+Confidential Rel BD=s3:c201.c229,c231.c511
+# Bolivia - bit 231
+Secret Releasable to BOL==s4:c201.c230,c232.c511
+Confidential Rel BL=s3:c201.c230,c232.c511
+# Brazil - bit 232
+Secret Releasable to BRA==s4:c201.c231,c233.c511
+Confidential Rel BR=s3:c201.c231,c233.c511
+# Barbados - bit 233
+Secret Releasable to BRB==s4:c201.c232,c234.c511
+Confidential Rel BB=s3:c201.c232,c234.c511
+# Brunei - bit 234
+Secret Releasable to BRN==s4:c201.c233,c235.c511
+Confidential Rel BX=s3:c201.c233,c235.c511
+# Bhutan - bit 235
+Secret Releasable to BTN==s4:c201.c234,c236.c511
+Confidential Rel BT=s3:c201.c234,c236.c511
+# Bouvet Island - bit 236
+Secret Releasable to BVT==s4:c201.c235,c237.c511
+Confidential Rel BV=s3:c201.c235,c237.c511
+# Botswana - bit 237
+Secret Releasable to BWA==s4:c201.c236,c238.c511
+Confidential Rel BC=s3:c201.c236,c238.c511
+# Central African Republic - bit 238
+Secret Releasable to CAF==s4:c201.c237,c239.c511
+Confidential Rel CT=s3:c201.c237,c239.c511
+# Canada - bit 239
+Secret Releasable to CAN==s4:c201.c238,c240.c511
+Confidential Rel CA=s3:c201.c238,c240.c511
+# Cocos (Keeling) Islands - bit 240 part of AUS
+Secret Releasable to CCK==s4:c201.c239,c241.c511
+Confidential Rel CK=s3:c201.c239,c241.c511
+# Switzerland - bit 241
+Secret Releasable to CHE==s4:c201.c240,c242.c511
+Confidential Rel SZ=s3:c201.c240,c242.c511
+# Chile - bit 242
+Secret Releasable to CHL==s4:c201.c241,c243.c511
+Confidential Rel CI=s3:c201.c241,c243.c511
+# China - bit 243
+Secret Releasable to CHN==s4:c201.c242,c244.c511
+Confidential Rel CH=s3:c201.c242,c244.c511
+# Cote d'Ivoire - bit 244
+Secret Releasable to CIV==s4:c201.c243,c245.c511
+Confidential Rel IV=s3:c201.c243,c245.c511
+# Cameroon - bit 245
+Secret Releasable to CMR==s4:c201.c244,c246.c511
+Confidential Rel CM=s3:c201.c244,c246.c511
+# Congo, Democratic Republic of the - bit 246
+Secret Releasable to COD==s4:c201.c245,c247.c511
+Confidential Rel CG=s3:c201.c245,c247.c511
+# Congo, Republic of the - bit 247
+Secret Releasable to COG==s4:c201.c246,c248.c511
+Confidential Rel CF=s3:c201.c246,c248.c511
+# Cook Islands - bit 248
+Secret Releasable to COK==s4:c201.c247,c249.c511
+Confidential Rel CW=s3:c201.c247,c249.c511
+# Colombia - bit 249
+Secret Releasable to COL==s4:c201.c248,c250.c511
+Confidential Rel CO=s3:c201.c248,c250.c511
+# Comoros - bit 250
+Secret Releasable to COM==s4:c201.c249,c251.c511
+Confidential Rel CN=s3:c201.c249,c251.c511
+# Cape Verde - bit 251
+Secret Releasable to CPV==s4:c201.c250,c252.c511
+Confidential Rel CV=s3:c201.c250,c252.c511
+# Costa Rica - bit 252
+Secret Releasable to CRI==s4:c201.c251,c253.c511
+Confidential Rel CS=s3:c201.c251,c253.c511
+# Cuba - bit 253
+Secret Releasable to CUB==s4:c201.c252,c254.c511
+Confidential Rel CU=s3:c201.c252,c254.c511
+# Christmas Island - bit 254
+Secret Releasable to CXR==s4:c201.c253,c255.c511
+Confidential Rel KT=s3:c201.c253,c255.c511
+# Cayman Islands - bit 255
+Secret Releasable to CYM==s4:c201.c254,c256.c511
+Confidential Rel CJ=s3:c201.c254,c256.c511
+# Cyprus - bit 256
+Secret Releasable to CYP==s4:c201.c255,c257.c511
+Confidential Rel CY=s3:c201.c255,c257.c511
+# Czech Republic - bit 257
+Secret Releasable to CZE==s4:c201.c256,c258.c511
+Confidential Rel EZ=s3:c201.c256,c258.c511
+# Germany - bit 258
+Secret Releasable to DEU==s4:c201.c257,c259.c511
+Confidential Rel GM=s3:c201.c257,c259.c511
+# Djibouti - bit 259
+Secret Releasable to DJI==s4:c201.c258,c260.c511
+Confidential Rel DJ=s3:c201.c258,c260.c511
+# Dominica - bit 260
+Secret Releasable to DMA==s4:c201.c259,c261.c511
+Confidential Rel DO=s3:c201.c259,c261.c511
+# Denmark - bit 261
+Secret Releasable to DNK==s4:c201.c260,c262.c511
+Confidential Rel DA=s3:c201.c260,c262.c511
+# Dominican Republic - bit 262
+Secret Releasable to DOM==s4:c201.c261,c263.c511
+Confidential Rel DR=s3:c201.c261,c263.c511
+# Algeria - bit 263
+Secret Releasable to DZA==s4:c201.c262,c264.c511
+Confidential Rel AG=s3:c201.c262,c264.c511
+# Ecuador - bit 264
+Secret Releasable to ECU==s4:c201.c263,c265.c511
+Confidential Rel EC=s3:c201.c263,c265.c511
+# Egypt - bit 265
+Secret Releasable to EGY==s4:c201.c264,c266.c511
+Confidential Rel EG=s3:c201.c264,c266.c511
+# Eritrea - bit 266
+Secret Releasable to ERI==s4:c201.c265,c267.c511
+Confidential Rel ER=s3:c201.c265,c267.c511
+# Western Sahara - bit 267
+Secret Releasable to ESH==s4:c201.c266,c268.c511
+Confidential Rel WI=s3:c201.c266,c268.c511
+# Spain - bit 268
+Secret Releasable to ESP==s4:c201.c267,c269.c511
+Confidential Rel SP=s3:c201.c267,c269.c511
+# Estonia - bit 269
+Secret Releasable to EST==s4:c201.c268,c270.c511
+Confidential Rel EN=s3:c201.c268,c270.c511
+# Ethiopia - bit 270
+Secret Releasable to ETH==s4:c201.c269,c271.c511
+Confidential Rel ET=s3:c201.c269,c271.c511
+# Finland - bit 271
+Secret Releasable to FIN==s4:c201.c270,c272.c511
+Confidential Rel FI=s3:c201.c270,c272.c511
+# Fiji - bit 272
+Secret Releasable to FJI==s4:c201.c271,c273.c511
+Confidential Rel FJ=s3:c201.c271,c273.c511
+# Falkland Islands (Islas Malvinas) - bit 273
+Secret Releasable to FLK==s4:c201.c272,c274.c511
+Confidential Rel FK=s3:c201.c272,c274.c511
+# France - bit 274
+Secret Releasable to FRA==s4:c201.c273,c275.c511
+Confidential Rel FR=s3:c201.c273,c275.c511
+# Faroe Islands - bit 275
+Secret Releasable to FRO==s4:c201.c274,c276.c511
+Confidential Rel FO=s3:c201.c274,c276.c511
+# Micronesia, Federated States of - bit 276
+Secret Releasable to FSM==s4:c201.c275,c277.c511
+Confidential Rel FM=s3:c201.c275,c277.c511
+# Gabon - bit 277
+Secret Releasable to GAB==s4:c201.c276,c278.c511
+Confidential Rel GB=s3:c201.c276,c278.c511
+# United Kingdom - bit 278
+Secret Releasable to GBR==s4:c201.c277,c279.c511
+Confidential Rel UK=s3:c201.c277,c279.c511
+# Georgia - bit 279
+Secret Releasable to GEO==s4:c201.c278,c280.c511
+Confidential Rel GG=s3:c201.c278,c280.c511
+# Guernsey - bit 280 part of UK
+Secret Releasable to GGY==s4:c201.c279,c281.c511
+Confidential Rel GK=s3:c201.c279,c281.c511
+# Ghana - bit 281
+Secret Releasable to GHA==s4:c201.c280,c282.c511
+Confidential Rel GH=s3:c201.c280,c282.c511
+# Gibraltar - bit 282
+Secret Releasable to GIB==s4:c201.c281,c283.c511
+Confidential Rel GI=s3:c201.c281,c283.c511
+# Guinea - bit 283
+Secret Releasable to GIN==s4:c201.c282,c284.c511
+Confidential Rel GV=s3:c201.c282,c284.c511
+# Guadeloupe - bit 284
+Secret Releasable to GLP==s4:c201.c283,c285.c511
+Confidential Rel GP=s3:c201.c283,c285.c511
+# Gambia, The - bit 285
+Secret Releasable to GMB==s4:c201.c284,c286.c511
+Confidential Rel GA=s3:c201.c284,c286.c511
+# Guinea-Bissau - bit 286
+Secret Releasable to GNB==s4:c201.c285,c287.c511
+Confidential Rel PU=s3:c201.c285,c287.c511
+# Equatorial Guinea - bit 287
+Secret Releasable to GNQ==s4:c201.c286,c288.c511
+Confidential Rel EK=s3:c201.c286,c288.c511
+# Greece - bit 288
+Secret Releasable to GRC==s4:c201.c287,c289.c511
+Confidential Rel GR=s3:c201.c287,c289.c511
+# Grenada - bit 289
+Secret Releasable to GRD==s4:c201.c288,c290.c511
+Confidential Rel GJ=s3:c201.c288,c290.c511
+# Greenland - bit 290
+Secret Releasable to GRL==s4:c201.c289,c291.c511
+Confidential Rel GL=s3:c201.c289,c291.c511
+# Guatemala - bit 291
+Secret Releasable to GTM==s4:c201.c290,c292.c511
+Confidential Rel GT=s3:c201.c290,c292.c511
+# French Guiana - bit 292
+Secret Releasable to GUF==s4:c201.c291,c293.c511
+Confidential Rel FG=s3:c201.c291,c293.c511
+# Guam - bit 293
+Secret Releasable to GUM==s4:c201.c292,c294.c511
+Confidential Rel GQ=s3:c201.c292,c294.c511
+# Guyana - bit 294
+Secret Releasable to GUY==s4:c201.c293,c295.c511
+Confidential Rel GY=s3:c201.c293,c295.c511
+# Hong Kong - bit 295
+Secret Releasable to HKG==s4:c201.c294,c296.c511
+Confidential Rel HK=s3:c201.c294,c296.c511
+# Heard Island and McDonald Islands - bit 296
+Secret Releasable to HMD==s4:c201.c295,c297.c511
+Confidential Rel HM=s3:c201.c295,c297.c511
+# Honduras - bit 297
+Secret Releasable to HND==s4:c201.c296,c298.c511
+Confidential Rel HO=s3:c201.c296,c298.c511
+# Croatia - bit 298
+Secret Releasable to HRV==s4:c201.c297,c299.c511
+Confidential Rel HR=s3:c201.c297,c299.c511
+# Haiti - bit 299
+Secret Releasable to HTI==s4:c201.c298,c300.c511
+Confidential Rel HA=s3:c201.c298,c300.c511
+# Hungary - bit 300
+Secret Releasable to HUN==s4:c201.c299,c301.c511
+Confidential Rel HU=s3:c201.c299,c301.c511
+# Indonesia - bit 301
+Secret Releasable to IDN==s4:c201.c300,c302.c511
+Confidential Rel ID=s3:c201.c300,c302.c511
+# Isle of Man - bit 302 part of UK
+Secret Releasable to IMN==s4:c201.c301,c303.c511
+Confidential Rel IM=s3:c201.c301,c303.c511
+# India - bit 303
+Secret Releasable to IND==s4:c201.c302,c304.c511
+Confidential Rel IN=s3:c201.c302,c304.c511
+# British Indian Ocean Territory - bit 304
+Secret Releasable to IOT==s4:c201.c303,c305.c511
+Confidential Rel IO=s3:c201.c303,c305.c511
+# Ireland - bit 305
+Secret Releasable to IRL==s4:c201.c304,c306.c511
+Confidential Rel EI=s3:c201.c304,c306.c511
+# Iran - bit 306
+Secret Releasable to IRN==s4:c201.c305,c307.c511
+Confidential Rel IR=s3:c201.c305,c307.c511
+# Iraq - bit 307
+Secret Releasable to IRQ==s4:c201.c306,c308.c511
+Confidential Rel IZ=s3:c201.c306,c308.c511
+# Iceland - bit 308
+Secret Releasable to ISL==s4:c201.c307,c309.c511
+Confidential Rel IC=s3:c201.c307,c309.c511
+# Israel - bit 309
+Secret Releasable to ISR==s4:c201.c308,c310.c511
+Confidential Rel IS=s3:c201.c308,c310.c511
+# Italy - bit 310
+Secret Releasable to ITA==s4:c201.c309,c311.c511
+Confidential Rel IT=s3:c201.c309,c311.c511
+# Jamaica - bit 311
+Secret Releasable to JAM==s4:c201.c310,c312.c511
+Confidential Rel JM=s3:c201.c310,c312.c511
+# Jersey - bit 312 part of UK
+Secret Releasable to JEY==s4:c201.c311,c313.c511
+Confidential Rel JE=s3:c201.c311,c313.c511
+# Jordan - bit 313
+Secret Releasable to JOR==s4:c201.c312,c314.c511
+Confidential Rel JO=s3:c201.c312,c314.c511
+# Japan - bit 314
+Secret Releasable to JPN==s4:c201.c313,c315.c511
+Confidential Rel JA=s3:c201.c313,c315.c511
+# Kazakhstan - bit 315
+Secret Releasable to KAZ==s4:c201.c314,c316.c511
+Confidential Rel KZ=s3:c201.c314,c316.c511
+# Kenya - bit 316
+Secret Releasable to KEN==s4:c201.c315,c317.c511
+Confidential Rel KE=s3:c201.c315,c317.c511
+# Kyrgyzstan - bit 317
+Secret Releasable to KGZ==s4:c201.c316,c318.c511
+Confidential Rel KG=s3:c201.c316,c318.c511
+# Cambodia - bit 318
+Secret Releasable to KHM==s4:c201.c317,c319.c511
+Confidential Rel CB=s3:c201.c317,c319.c511
+# Kiribati - bit 319
+Secret Releasable to KIR==s4:c201.c318,c320.c511
+Confidential Rel KR=s3:c201.c318,c320.c511
+# Saint Kitts and Nevis - bit 320
+Secret Releasable to KNA==s4:c201.c319,c321.c511
+Confidential Rel SC=s3:c201.c319,c321.c511
+# Korea, South - bit 321
+Secret Releasable to KOR==s4:c201.c320,c322.c511
+Confidential Rel KS=s3:c201.c320,c322.c511
+# Kuwait - bit 322
+Secret Releasable to KWT==s4:c201.c321,c323.c511
+Confidential Rel KU=s3:c201.c321,c323.c511
+# Laos - bit 323
+Secret Releasable to LAO==s4:c201.c322,c324.c511
+Confidential Rel LA=s3:c201.c322,c324.c511
+# Lebanon - bit 324
+Secret Releasable to LBN==s4:c201.c323,c325.c511
+Confidential Rel LE=s3:c201.c323,c325.c511
+# Liberia - bit 325
+Secret Releasable to LBR==s4:c201.c324,c326.c511
+Confidential Rel LI=s3:c201.c324,c326.c511
+# Libya - bit 326
+Secret Releasable to LBY==s4:c201.c325,c327.c511
+Confidential Rel LY=s3:c201.c325,c327.c511
+# Saint Lucia - bit 327
+Secret Releasable to LCA==s4:c201.c326,c328.c511
+Confidential Rel ST=s3:c201.c326,c328.c511
+# Liechtenstein - bit 328
+Secret Releasable to LIE==s4:c201.c327,c329.c511
+Confidential Rel LS=s3:c201.c327,c329.c511
+# Sri Lanka - bit 329
+Secret Releasable to LKA==s4:c201.c328,c330.c511
+Confidential Rel CE=s3:c201.c328,c330.c511
+# Lesotho - bit 330
+Secret Releasable to LSO==s4:c201.c329,c331.c511
+Confidential Rel LT=s3:c201.c329,c331.c511
+# Lithuania - bit 331
+Secret Releasable to LTU==s4:c201.c330,c332.c511
+Confidential Rel LH=s3:c201.c330,c332.c511
+# Luxembourg - bit 332
+Secret Releasable to LUX==s4:c201.c331,c333.c511
+Confidential Rel LU=s3:c201.c331,c333.c511
+# Latvia - bit 333
+Secret Releasable to LVA==s4:c201.c332,c334.c511
+Confidential Rel LG=s3:c201.c332,c334.c511
+# Macau - bit 334
+Secret Releasable to MAC==s4:c201.c333,c335.c511
+Confidential Rel MC=s3:c201.c333,c335.c511
+# Saint Martin - bit 335
+Secret Releasable to MAF==s4:c201.c334,c336.c511
+Confidential Rel RN=s3:c201.c334,c336.c511
+# Morocco - bit 336
+Secret Releasable to MAR==s4:c201.c335,c337.c511
+Confidential Rel MO=s3:c201.c335,c337.c511
+# Monaco - bit 337
+Secret Releasable to MCO==s4:c201.c336,c338.c511
+Confidential Rel MN=s3:c201.c336,c338.c511
+# Moldova - bit 338
+Secret Releasable to MDA==s4:c201.c337,c339.c511
+Confidential Rel MD=s3:c201.c337,c339.c511
+# Madagascar - bit 339
+Secret Releasable to MDG==s4:c201.c338,c340.c511
+Confidential Rel MA=s3:c201.c338,c340.c511
+# Maldives - bit 340
+Secret Releasable to MDV==s4:c201.c339,c341.c511
+Confidential Rel MV=s3:c201.c339,c341.c511
+# Mexico - bit 341
+Secret Releasable to MEX==s4:c201.c340,c342.c511
+Confidential Rel MX=s3:c201.c340,c342.c511
+# Marshall Islands - bit 342
+Secret Releasable to MHL==s4:c201.c341,c343.c511
+Confidential Rel RM=s3:c201.c341,c343.c511
+# Macedonia - bit 343 part of FYR
+Secret Releasable to MKD==s4:c201.c342,c344.c511
+Confidential Rel MK=s3:c201.c342,c344.c511
+# Mali - bit 344
+Secret Releasable to MLI==s4:c201.c343,c345.c511
+Confidential Rel ML=s3:c201.c343,c345.c511
+# Malta - bit 345
+Secret Releasable to MLT==s4:c201.c344,c346.c511
+Confidential Rel MT=s3:c201.c344,c346.c511
+# Burma - bit 346
+Secret Releasable to MMR==s4:c201.c345,c347.c511
+Confidential Rel BM=s3:c201.c345,c347.c511
+# Montenegro - bit 347
+Secret Releasable to MNE==s4:c201.c346,c348.c511
+Confidential Rel MJ=s3:c201.c346,c348.c511
+# Mongolia - bit 348
+Secret Releasable to MNG==s4:c201.c347,c349.c511
+Confidential Rel MG=s3:c201.c347,c349.c511
+# Northern Mariana Islands - bit 349
+Secret Releasable to MNP==s4:c201.c348,c350.c511
+Confidential Rel CQ=s3:c201.c348,c350.c511
+# Mozambique - bit 350
+Secret Releasable to MOZ==s4:c201.c349,c351.c511
+Confidential Rel MZ=s3:c201.c349,c351.c511
+# Mauritania - bit 351
+Secret Releasable to MRT==s4:c201.c350,c352.c511
+Confidential Rel MR=s3:c201.c350,c352.c511
+# Montserrat - bit 352
+Secret Releasable to MSR==s4:c201.c351,c353.c511
+Confidential Rel MH=s3:c201.c351,c353.c511
+# Martinique - bit 353
+Secret Releasable to MTQ==s4:c201.c352,c354.c511
+Confidential Rel MB=s3:c201.c352,c354.c511
+# Mauritius - bit 354
+Secret Releasable to MUS==s4:c201.c353,c355.c511
+Confidential Rel MP=s3:c201.c353,c355.c511
+# Malawi - bit 355
+Secret Releasable to MWI==s4:c201.c354,c356.c511
+Confidential Rel MI=s3:c201.c354,c356.c511
+# Malaysia - bit 356
+Secret Releasable to MYS==s4:c201.c355,c357.c511
+Confidential Rel MY=s3:c201.c355,c357.c511
+# Mayotte - bit 357 part of FRA
+Secret Releasable to MYT==s4:c201.c356,c358.c511
+Confidential Rel MF=s3:c201.c356,c358.c511
+# Namibia - bit 358
+Secret Releasable to NAM==s4:c201.c357,c359.c511
+Confidential Rel WA=s3:c201.c357,c359.c511
+# New Caledonia - bit 359
+Secret Releasable to NCL==s4:c201.c358,c360.c511
+Confidential Rel NC=s3:c201.c358,c360.c511
+# Niger - bit 360
+Secret Releasable to NER==s4:c201.c359,c361.c511
+Confidential Rel NG=s3:c201.c359,c361.c511
+# Norfolk Island - bit 361
+Secret Releasable to NFK==s4:c201.c360,c362.c511
+Confidential Rel NF=s3:c201.c360,c362.c511
+# Nigeria - bit 362
+Secret Releasable to NGA==s4:c201.c361,c363.c511
+Confidential Rel NI=s3:c201.c361,c363.c511
+# Nicaragua - bit 363
+Secret Releasable to NIC==s4:c201.c362,c364.c511
+Confidential Rel NU=s3:c201.c362,c364.c511
+# Niue - bit 364
+Secret Releasable to NIU==s4:c201.c363,c365.c511
+Confidential Rel NE=s3:c201.c363,c365.c511
+# Netherlands - bit 365
+Secret Releasable to NLD==s4:c201.c364,c366.c511
+Confidential Rel NL=s3:c201.c364,c366.c511
+# Norway - bit 366
+Secret Releasable to NOR==s4:c201.c365,c367.c511
+Confidential Rel NO=s3:c201.c365,c367.c511
+# Nepal - bit 367
+Secret Releasable to NPL==s4:c201.c366,c368.c511
+Confidential Rel NP=s3:c201.c366,c368.c511
+# Nauru - bit 368
+Secret Releasable to NRU==s4:c201.c367,c369.c511
+Confidential Rel NR=s3:c201.c367,c369.c511
+# New Zealand - bit 369
+Secret Releasable to NZL==s4:c201.c368,c370.c511
+Confidential Rel NZ=s3:c201.c368,c370.c511
+# Oman - bit 370
+Secret Releasable to OMN==s4:c201.c369,c371.c511
+Confidential Rel MU=s3:c201.c369,c371.c511
+# Pakistan - bit 371
+Secret Releasable to PAK==s4:c201.c370,c372.c511
+Confidential Rel PK=s3:c201.c370,c372.c511
+# Panama - bit 372
+Secret Releasable to PAN==s4:c201.c371,c373.c511
+Confidential Rel PM=s3:c201.c371,c373.c511
+# Pitcairn Islands - bit 373
+Secret Releasable to PCN==s4:c201.c372,c374.c511
+Confidential Rel PC=s3:c201.c372,c374.c511
+# Peru - bit 374
+Secret Releasable to PER==s4:c201.c373,c375.c511
+Confidential Rel PE=s3:c201.c373,c375.c511
+# Philippines - bit 375
+Secret Releasable to PHL==s4:c201.c374,c376.c511
+Confidential Rel RP=s3:c201.c374,c376.c511
+# Palau - bit 376
+Secret Releasable to PLW==s4:c201.c375,c377.c511
+Confidential Rel PS=s3:c201.c375,c377.c511
+# Papua New Guinea - bit 377
+Secret Releasable to PNG==s4:c201.c376,c378.c511
+Confidential Rel PP=s3:c201.c376,c378.c511
+# Poland - bit 378
+Secret Releasable to POL==s4:c201.c377,c379.c511
+Confidential Rel PL=s3:c201.c377,c379.c511
+# Puerto Rico - bit 379
+Secret Releasable to PRI==s4:c201.c378,c380.c511
+Confidential Rel RQ=s3:c201.c378,c380.c511
+# Korea, North - bit 380
+Secret Releasable to PRK==s4:c201.c379,c381.c511
+Confidential Rel KN=s3:c201.c379,c381.c511
+# Portugal - bit 381
+Secret Releasable to PRT==s4:c201.c380,c382.c511
+Confidential Rel PO=s3:c201.c380,c382.c511
+# Paraguay - bit 382
+Secret Releasable to PRY==s4:c201.c381,c383.c511
+Confidential Rel PA=s3:c201.c381,c383.c511
+# Gaza Strip - bit 383
+Secret Releasable to PSE==s4:c201.c382,c384.c511
+Confidential Rel GZ=s3:c201.c382,c384.c511
+# West Bank - bit 383
+Confidential Rel WE=s3:c201.c382,c384.c511
+# French Polynesia - bit 384
+Secret Releasable to PYF==s4:c201.c383,c385.c511
+Confidential Rel FP=s3:c201.c383,c385.c511
+# Qatar - bit 385
+Secret Releasable to QAT==s4:c201.c384,c386.c511
+Confidential Rel QA=s3:c201.c384,c386.c511
+# Reunion - bit 386
+Secret Releasable to REU==s4:c201.c385,c387.c511
+Confidential Rel RE=s3:c201.c385,c387.c511
+# Romania - bit 387
+Secret Releasable to ROU==s4:c201.c386,c388.c511
+Confidential Rel RO=s3:c201.c386,c388.c511
+# Russia - bit 388
+Secret Releasable to RUS==s4:c201.c387,c389.c511
+Confidential Rel RS=s3:c201.c387,c389.c511
+# Rwanda - bit 389
+Secret Releasable to RWA==s4:c201.c388,c390.c511
+Confidential Rel RW=s3:c201.c388,c390.c511
+# Saudi Arabia - bit 390
+Secret Releasable to SAU==s4:c201.c389,c391.c511
+Confidential Rel SA=s3:c201.c389,c391.c511
+# Sudan - bit 391
+Secret Releasable to SDN==s4:c201.c390,c392.c511
+Confidential Rel SU=s3:c201.c390,c392.c511
+# Senegal - bit 392
+Secret Releasable to SEN==s4:c201.c391,c393.c511
+Confidential Rel SG=s3:c201.c391,c393.c511
+# Singapore - bit 393
+Secret Releasable to SGP==s4:c201.c392,c394.c511
+Confidential Rel SN=s3:c201.c392,c394.c511
+# South Georgia and the Islands - bit 394
+Secret Releasable to SGS==s4:c201.c393,c395.c511
+Confidential Rel SX=s3:c201.c393,c395.c511
+# Saint Helena - bit 395
+Secret Releasable to SHN==s4:c201.c394,c396.c511
+Confidential Rel SH=s3:c201.c394,c396.c511
+# Svalbard - bit 396
+Secret Releasable to SJM==s4:c201.c395,c397.c511
+Confidential Rel SV=s3:c201.c395,c397.c511
+# Solomon Islands - bit 397
+Secret Releasable to SLB==s4:c201.c396,c398.c511
+Confidential Rel BP=s3:c201.c396,c398.c511
+# Sierra Leone - bit 398
+Secret Releasable to SLE==s4:c201.c397,c399.c511
+Confidential Rel SL=s3:c201.c397,c399.c511
+# El Salvador - bit 399
+Secret Releasable to SLV==s4:c201.c398,c400.c511
+Confidential Rel ES=s3:c201.c398,c400.c511
+# San Marino - bit 400
+Secret Releasable to SMR==s4:c201.c399,c401.c511
+Confidential Rel SM=s3:c201.c399,c401.c511
+# Somalia - bit 401
+Secret Releasable to SOM==s4:c201.c400,c402.c511
+Confidential Rel SO=s3:c201.c400,c402.c511
+# Saint Pierre and Miquelon - bit 402
+Secret Releasable to SPM==s4:c201.c401,c403.c511
+Confidential Rel SB=s3:c201.c401,c403.c511
+# Serbia - bit 403
+Secret Releasable to SRB==s4:c201.c402,c404.c511
+Confidential Rel RB=s3:c201.c402,c404.c511
+# Sao Tome and Principe - bit 404
+Secret Releasable to STP==s4:c201.c403,c405.c511
+Confidential Rel TP=s3:c201.c403,c405.c511
+# Suriname - bit 405
+Secret Releasable to SUR==s4:c201.c404,c406.c511
+Confidential Rel NS=s3:c201.c404,c406.c511
+# Slovakia - bit 406
+Secret Releasable to SVK==s4:c201.c405,c407.c511
+Confidential Rel LO=s3:c201.c405,c407.c511
+# Slovenia - bit 407
+Secret Releasable to SVN==s4:c201.c406,c408.c511
+Confidential Rel SI=s3:c201.c406,c408.c511
+# Sweden - bit 408
+Secret Releasable to SWE==s4:c201.c407,c409.c511
+Confidential Rel SW=s3:c201.c407,c409.c511
+# Swaziland - bit 409
+Secret Releasable to SWZ==s4:c201.c408,c410.c511
+Confidential Rel WZ=s3:c201.c408,c410.c511
+# Seychelles - bit 410
+Secret Releasable to SYC==s4:c201.c409,c411.c511
+Confidential Rel SE=s3:c201.c409,c411.c511
+# Syria - bit 411
+Secret Releasable to SYR==s4:c201.c410,c412.c511
+Confidential Rel SY=s3:c201.c410,c412.c511
+# Turks and Caicos Islands - bit 412
+Secret Releasable to TCA==s4:c201.c411,c413.c511
+Confidential Rel TK=s3:c201.c411,c413.c511
+# Chad - bit 413
+Secret Releasable to TCD==s4:c201.c412,c414.c511
+Confidential Rel CD=s3:c201.c412,c414.c511
+# Togo - bit 414
+Secret Releasable to TGO==s4:c201.c413,c415.c511
+Confidential Rel TO=s3:c201.c413,c415.c511
+# Thailand - bit 415
+Secret Releasable to THA==s4:c201.c414,c416.c511
+Confidential Rel TH=s3:c201.c414,c416.c511
+# Tajikistan - bit 416
+Secret Releasable to TJK==s4:c201.c415,c417.c511
+Confidential Rel TI=s3:c201.c415,c417.c511
+# Tokelau - bit 417
+Secret Releasable to TKL==s4:c201.c416,c418.c511
+Confidential Rel TL=s3:c201.c416,c418.c511
+# Turkmenistan - bit 418
+Secret Releasable to TKM==s4:c201.c417,c419.c511
+Confidential Rel TX=s3:c201.c417,c419.c511
+# Timor-Leste - bit 419
+Secret Releasable to TLS==s4:c201.c418,c420.c511
+Confidential Rel TT=s3:c201.c418,c420.c511
+# Tonga - bit 420
+Secret Releasable to TON==s4:c201.c419,c421.c511
+Confidential Rel TN=s3:c201.c419,c421.c511
+# Trinidad and Tobago - bit 421
+Secret Releasable to TTO==s4:c201.c420,c422.c511
+Confidential Rel TD=s3:c201.c420,c422.c511
+# Tunisia - bit 422
+Secret Releasable to TUN==s4:c201.c421,c423.c511
+Confidential Rel TS=s3:c201.c421,c423.c511
+# Turkey - bit 423
+Secret Releasable to TUR==s4:c201.c422,c424.c511
+Confidential Rel TU=s3:c201.c422,c424.c511
+# Tuvalu - bit 424
+Secret Releasable to TUV==s4:c201.c423,c425.c511
+Confidential Rel TV=s3:c201.c423,c425.c511
+# Taiwan - bit 425
+Secret Releasable to TWN==s4:c201.c424,c426.c511
+Confidential Rel TW=s3:c201.c424,c426.c511
+# Tanzania - bit 426
+Secret Releasable to TZA==s4:c201.c425,c427.c511
+Confidential Rel TZ=s3:c201.c425,c427.c511
+# Uganda - bit 427
+Secret Releasable to UGA==s4:c201.c426,c428.c511
+Confidential Rel UG=s3:c201.c426,c428.c511
+# Ukraine - bit 428
+Secret Releasable to UKR==s4:c201.c427,c429.c511
+Confidential Rel UP=s3:c201.c427,c429.c511
+# Uruguay - bit 429
+Secret Releasable to URY==s4:c201.c428,c430.c511
+Confidential Rel UY=s3:c201.c428,c430.c511
+# United States - bit 430
+Secret Releasable to USA==s4:c201.c429,c431.c511
+Confidential Rel US=s3:c201.c429,c431.c511
+# Uzbekistan - bit 431
+Secret Releasable to UZB==s4:c201.c430,c432.c511
+Confidential Rel UZ=s3:c201.c430,c432.c511
+# Holy See (Vatican City) - bit 432
+Secret Releasable to VAT==s4:c201.c431,c433.c511
+Confidential Rel VT=s3:c201.c431,c433.c511
+# Saint Vincent and the Grenadines - bit 433
+Secret Releasable to VCT==s4:c201.c432,c434.c511
+Confidential Rel VC=s3:c201.c432,c434.c511
+# Venezuela - bit 434
+Secret Releasable to VEN==s4:c201.c433,c435.c511
+Confidential Rel VE=s3:c201.c433,c435.c511
+# British Virgin Islands - bit 435
+Secret Releasable to VGB==s4:c201.c434,c436.c511
+Confidential Rel VI=s3:c201.c434,c436.c511
+# Virgin Islands - bit 436
+Secret Releasable to VIR==s4:c201.c435,c437.c511
+Confidential Rel VQ=s3:c201.c435,c437.c511
+# Vietnam - bit 437
+Secret Releasable to VNM==s4:c201.c436,c438.c511
+Confidential Rel VM=s3:c201.c436,c438.c511
+# Vanuatu - bit 438
+Secret Releasable to VUT==s4:c201.c437,c439.c511
+Confidential Rel NH=s3:c201.c437,c439.c511
+# Wallis and Futuna - bit 439
+Secret Releasable to WLF==s4:c201.c438,c440.c511
+Confidential Rel WF=s3:c201.c438,c440.c511
+# Samoa - bit 440
+Secret Releasable to WSM==s4:c201.c439,c441.c511
+Confidential Rel WS=s3:c201.c439,c441.c511
+# Yemen - bit 441
+Secret Releasable to YEM==s4:c201.c440,c442.c511
+Confidential Rel YM=s3:c201.c440,c442.c511
+# South Africa - bit 442
+Secret Releasable to ZAF==s4:c201.c441,c443.c511
+Confidential Rel SF=s3:c201.c441,c443.c511
+# Zambia - bit 443
+Secret Releasable to ZMB==s4:c201.c442,c444.c511
+Confidential Rel ZA=s3:c201.c442,c444.c511
+# Zimbabwe - bit 444
+Secret Releasable to ZWE==s4:c201.c443,c445.c511
+Confidential Rel ZI=s3:c201.c443,c445.c511
diff --git a/test/setrans.test b/test/setrans.test
new file mode 100644
index 0000000..fcfaac2
--- /dev/null
+++ b/test/setrans.test
@@ -0,0 +1,51 @@
+SystemLow==s0
+SystemHigh==s15:c0.c1023
+SystemLow-SystemHigh==s0-s15:c0.c1023
+
+Unclassified==s1
+U=s1
+Restricted==s2:c200.c511
+R=s2:c200.c511
+Confidential==s3:c200.c511
+C=s3:c200.c511
+Secret==s4:c200.c511
+S=s4:c200.c511
+Top Secret==s5:c200.c511
+TS=s5:c200.c511
+
+Unclassified-Unclassified=s1
+Unclassified-Restricted==s1-s2:c200.c511
+Unclassified-Confidential==s1-s3:c200.c511
+Unclassified-Secret==s1-s4:c200.c511
+Unclassified-Top Secret==s1-s5:c200.c511
+
+U-U=s1
+U-R=s1-s2:c200.c511
+U-C=s1-s3:c200.c511
+U-S=s1-s4:c200.c511
+U-TS=s1-s5:c200.c511
+
+R-U=s2:c200.c511-s1
+R-R=s2:c200.c511
+R-C=s2:c200.c511-s3:c200.c511
+R-S=s2:c200.c511-s4:c200.c511
+R-TS=s2:c200.c511-s5:c200.c511
+
+C-U=s3:c200.c511-s1
+C-R=s3:c200.c511-s2:c200.c511
+C-C=s3:c200.c511
+C-S=s3:c200.c511-s4:c200.c511
+C-TS=s3:c200.c511-s5:c200.c511
+
+S-U=s4:c200.c511-s1
+S-R=s4:c200.c511-s2:c200.c511
+S-C=s4:c200.c511-s3:c200.c511
+S-S=s4:c200.c511
+S-TS=s4:c200.c511-s5:c200.c511
+
+TS-U=s5:c200.c511-s1
+TS-R=s5:c200.c511-s2:c200.c511
+TS-C=s5:c200.c511-s3:c200.c511
+TS-S=s5:c200.c511-s4:c200.c511
+TS-TS=s5:c200.c511
+
diff --git a/utils/Makefile b/utils/Makefile
new file mode 100644
index 0000000..1ffb027
--- /dev/null
+++ b/utils/Makefile
@@ -0,0 +1,41 @@
+# Installation directories.
+PREFIX ?= $(DESTDIR)/usr
+BINDIR ?= $(PREFIX)/sbin
+
+ARCH = $(shell uname -i)
+ifeq "$(ARCH)" "x86_64"
+ # In case of 64 bit system, use these lines
+ LIBDIR=/usr/lib64
+else
+ifeq "$(ARCH)" "i686"
+ # In case of 32 bit system, use these lines
+ LIBDIR=/usr/lib
+else
+ifeq "$(ARCH)" "i386"
+ # In case of 32 bit system, use these lines
+ LIBDIR=/usr/lib
+endif
+endif
+endif
+
+
+CFLAGS ?= -Wall
+override CFLAGS += -I../src -D_GNU_SOURCE
+LDLIBS += -L../src ../src/mcstrans.o ../src/mls_level.o -lselinux -lpcre $(LIBDIR)/libsepol.a
+
+TARGETS=$(patsubst %.c,%,$(wildcard *.c))
+
+all: $(TARGETS)
+
+install: all
+ -mkdir -p $(BINDIR)
+ install -m 755 $(TARGETS) $(BINDIR)
+
+test:
+ ./mlstrans-test-runner.py ../test/*.test
+
+clean:
+ rm -f $(TARGETS) *.o *~ \#*
+
+relabel:
+
diff --git a/utils/callgrind-mcstransd b/utils/callgrind-mcstransd
new file mode 100755
index 0000000..f494b24
--- /dev/null
+++ b/utils/callgrind-mcstransd
@@ -0,0 +1,5 @@
+#!/bin/bash
+service mcstrans stop
+cd ~root
+runcon -u system_u -r system_r -t setrans_t -l s15:c0.c1023 -- valgrind --tool=callgrind /usr/src/redhat/BUILD/*/src/mcstransd
+run_init /etc/init.d/mcstrans start
diff --git a/utils/mlstrans-test-runner.py b/utils/mlstrans-test-runner.py
new file mode 100755
index 0000000..d8d420d
--- /dev/null
+++ b/utils/mlstrans-test-runner.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python -E
+import sys, re
+from selinux import *
+verbose = 0
+errors=0
+def untrans(trans, val):
+ global errors, verbose
+ (rc, raw) = selinux_trans_to_raw_context(trans)
+ if raw != val:
+ print "untrans: '%s' -> '%s' != '%s' FAILED" % (trans, raw, val)
+ errors += 1
+ else:
+ if verbose:
+ print "untrans: %s -> %s != %s SUCCESS" % (trans, raw, val)
+
+def trans(raw, val):
+ global errors, verbose
+ (rc, trans) = selinux_raw_to_trans_context(raw)
+ if trans != val:
+ print "trans: '%s' -> '%s' != '%s' FAILED" % (raw,trans, val)
+ errors += 1
+ else:
+ if verbose:
+ print "trans: %s -> %s != %s SUCCESS" % (raw, trans, val)
+
+if len(sys.argv) > 1 and sys.argv[1] == "-v":
+ verbose = 1
+
+for arg in sys.argv[1:]:
+ f=open(arg, 'r')
+ for line in f:
+ if line.startswith('#'):
+ continue
+ if not line.strip():
+ continue
+ line = line.rstrip('\n')
+# print line
+ if (line.find("==") != -1):
+ t,r=line.split("==");
+ untrans("a:b:c:" + t, "a:b:c:" + r)
+ trans("a:b:c:" + r, "a:b:c:" + t)
+ else:
+ t,r=line.split("=");
+ untrans("a:b:c:" + t, "a:b:c:" + r)
+ f.close()
+
+s = "s"
+if errors == 1: s = ""
+print "done with %d error%s" % (errors, s)
+
+sys.exit(errors)
+
+
diff --git a/utils/transcon.c b/utils/transcon.c
new file mode 100644
index 0000000..5189f0f
--- /dev/null
+++ b/utils/transcon.c
@@ -0,0 +1,30 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <errno.h>
+#include <string.h>
+#include <selinux/selinux.h>
+#include "mcstrans.h"
+
+void usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s context\n", progname);
+ exit(1);
+}
+
+int main(int argc, char **argv) {
+ security_context_t scon;
+ if ( argc != 2 ) usage(argv[0]);
+ if (init_translations()==0) {
+ if(trans_context(argv[1],&scon) == 0) {
+ printf("%s\n", scon);
+ freecon(scon);
+ return 0;
+ }
+ }
+ printf("Failed\n");
+ return -1;
+}
+
+
diff --git a/utils/untranscon.c b/utils/untranscon.c
new file mode 100644
index 0000000..f47b6ea
--- /dev/null
+++ b/utils/untranscon.c
@@ -0,0 +1,28 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <errno.h>
+#include <string.h>
+#include <selinux/selinux.h>
+#include "mcstrans.h"
+
+void usage(const char *progname)
+{
+ fprintf(stderr, "usage: %s context\n", progname);
+ exit(1);
+}
+int main(int argc, char **argv) {
+ security_context_t scon;
+ if ( argc != 2 ) usage(argv[0]);
+ if (init_translations()==0) {
+ if(untrans_context(argv[1],&scon) == 0) {
+ printf("%s\n", scon);
+ freecon(scon);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
diff --git a/utils/valgrind-mcstransd b/utils/valgrind-mcstransd
new file mode 100755
index 0000000..8890f9f
--- /dev/null
+++ b/utils/valgrind-mcstransd
@@ -0,0 +1,5 @@
+#!/bin/bash
+service mcstrans stop
+cd ~root
+runcon -u system_u -r system_r -t setrans_t -l s15:c0.c1023 -- valgrind -v --leak-check=full --show-reachable=yes /usr/src/redhat/BUILD/*/src/mcstransd
+run_init /etc/init.d/mcstrans start