Add prefix matching test for OIDs.
[gssweb.git] / json_gssapi / src / datamodel / GSSOID.cpp
1 /*
2  * Copyright (c) 2014, 2015 JANET(UK)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * 3. Neither the name of JANET(UK) nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31  * OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34
35 #include <string.h>
36
37 #include "GSSOID.h"
38 #include "../GSSException.h"
39
40 GSSOID::GSSOID(std::string oid_str)
41 {
42   init( GSSBuffer(oid_str) );
43 }
44
45 GSSOID::GSSOID(char *oid_str)
46 {
47   init( GSSBuffer(oid_str) );
48 }
49   
50 GSSOID::GSSOID(GSSBuffer oid_str)
51 {
52   init(oid_str);
53 }
54
55 GSSOID::GSSOID(gss_OID gssoid)
56 {
57   oid = gssoid;
58   this->gssInternal = true;
59 }
60
61 GSSOID::GSSOID ( const GSSOID &gssoid )
62 {
63   this->oid = gssoid.oid;
64   this->gssInternal = true;
65 }
66
67 void GSSOID::release()
68 {
69   OM_uint32 major, minor;
70   if ( (!this->gssInternal) && (oid != GSS_C_NO_OID) )
71   {
72     major = gss_release_oid(&minor, &(this->oid));
73     if (GSS_ERROR(major))
74     {
75       throw GSSException("Error in releasing a GSS OID", major, minor);
76     }
77   }
78 }
79
80 GSSOID::~GSSOID()
81 {
82   this->release();
83 }
84   
85 void GSSOID::init(GSSBuffer oid_str)
86 {
87   /* Variables */
88   OM_uint32 major, minor;
89   
90   /* Error checking */
91   /* Setup */
92   
93   /* Main */
94   major = gss_str_to_oid(&minor, oid_str.toGss(), &(this->oid));
95   if (GSS_ERROR(major))
96   {
97     throw GSSException("Error creating GSS OID", major, minor);
98   }
99   this->gssInternal = false;
100   
101   /* Cleanup */
102   /* Return */
103 }
104
105 std::string GSSOID::toString() const
106 {
107   /* Variables */
108   OM_uint32 major, minor;
109   gss_buffer_desc buf;
110   std::string ret;
111   
112   /* Error checking */
113   if (oid->length == 0)
114     return std::string("");
115   /* Setup */
116   /* Main */ 
117   major = gss_oid_to_str(&minor, this->oid, &buf);
118   if (GSS_ERROR(major))
119   {
120     throw GSSException("Error in creating a string representation of a GSS OID", 
121                        major, minor);
122   }
123   ret = std::string((char *)buf.value);
124   
125   /* Cleanup */
126   major = gss_release_buffer(&minor, &buf);
127   if (GSS_ERROR(major))
128   {
129     throw GSSException("Error releasing a gss_buffer", 
130                        major, minor);
131   }
132   
133   /* Return */ 
134   return(ret);
135 }
136
137 JSONObject *GSSOID::toJSONValue() const
138
139   std::string val = this->toString();
140   JSONObject *ret = new JSONObject( val.c_str() );
141   return(ret); 
142 }
143
144 bool GSSOID::setValue ( GSSBuffer buf )
145 {
146   init(buf);
147   return true;
148 }
149
150 bool GSSOID::setValue ( gss_OID gssOID )
151 {
152   oid = gssOID;
153   this->gssInternal = true;
154   return true;
155 }
156
157 bool GSSOID::matchesBaseOID ( const gss_OID_desc &base_oid )
158 {
159   /* Variables */
160   unsigned char *elements = reinterpret_cast <unsigned char*>(oid->elements);
161   
162   /* Error checking */
163   /* Setup */
164   /* Main processing */
165   // We can't match the prefex if we're not longer than the prefix.
166   if (oid->length <= base_oid.length)
167     return(false);
168
169   // Match the prefix itself.
170   if (memcmp(oid->elements, base_oid.elements, base_oid.length) != 0)
171     return(false);
172
173   // Constrain the suffix to a single OID segment.
174   // The break between segments is signified whenever an octet has 0 in
175   // its high-order bit.  Check that no octet between the prefix and the
176   // last octet has 0 in its high-order bit
177   for (size_t i = base_oid.length;
178        oid->length - 1 > i;
179        i++)
180   {
181     if( !(elements[i] & 0x80) )
182       return(false);
183   }
184
185   // Add a sanity check that the last octet has 0 in its high-order bit.
186   if( elements[oid->length - 1] & 0x80 )
187     return(false);
188   
189   /* Cleanup */
190   // No memory allocated, just typecast - nothing to clean up
191   
192   /* Return */
193   return(true);
194 }
195