Move util_ files into utils directory, move main.cpp into src
[gssweb.git] / json_gssapi / src / commands / GSSInitSecContext.cpp
1 /*
2  * Copyright (c) 2014, 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 // MRW -- Add proper copyright boilerplate to all files
35
36 #include "GSSInitSecContext.h"
37 #include "GSSException.h"
38 #include <cache/GSSContextCache.h>
39 #include <cache/GSSNameCache.h>
40 #include <datamodel/GSSName.h>
41 #include <gssapi.h>
42 #include <stdexcept>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include "utils/util_base64.h"
47
48 void
49 GSSInitSecContext::execute()
50 {
51   /* Variables */
52   gss_OID actual_mech_type;
53   
54   /* Error checking */
55   
56   /* Setup */
57   if (output_token.length > 0)
58     retVal = gss_release_buffer(&minor_status, &output_token);
59
60   /* Main */
61   // MRW -- fix so that this uses all of the vars from the object 
62   retVal = function(
63     &minor_status,
64     GSS_C_NO_CREDENTIAL,
65     &context_handle,
66     targetName.toGss(),
67     mechType.toGss(),
68     req_flags,
69     time_req,
70     GSS_C_NO_CHANNEL_BINDINGS,
71     &input_token,
72     &actual_mech_type,
73     &output_token,
74     &ret_flags,
75     &time_rec);
76   
77   if ( GSS_ERROR(this->retVal) )
78   {
79     // MRW -- steal code from import name
80     std::string errMsg;
81     errMsg += "Cannot init_sec_context: ";
82     throw GSSException(errMsg.c_str(), this->retVal, this->minor_status, mechType.toGss());
83   }
84   
85   actualMechType.setValue(actual_mech_type);
86   
87   context.setContext(context_handle, true);
88   contextKey = GSSContextCache::instance()->store(context);
89   
90   /* Cleanup */
91   
92   /* Return */
93 }
94
95 const char* GSSInitSecContext::getTargetDisplayName()
96 {
97   /* Variables */
98   gss_buffer_desc output_name;
99   gss_OID output_type;
100   OM_uint32 major, minor;
101   const char *ret;
102   
103   /* error checking */
104   
105   /* Setup */
106   
107   /* Main */
108   major = gss_display_name(&minor, target_name, &output_name, &output_type);
109   if (major == GSS_S_COMPLETE)
110     ret = (const char *)output_name.value;
111   else
112     ret = NULL;
113   
114   /* cleanup */
115   
116   /* return */
117   return( ret );
118 }
119
120 bool GSSInitSecContext::loadParameters(JSONObject *params)
121 {
122   /* Variables */
123   std::string key;
124   std::string token;
125   
126   /* Error checking */
127   if ( params->isNull() )
128     return true;
129   
130   /* Setup */
131   
132   /* Main processing */
133   // MRW -- finish parsing all of the variables
134   // claimant_cred_handle
135
136   // context_handle
137   if (!(params->get("context_handle").isNull() ||
138         (params->get("context_handle").isString() &&
139          std::string("") == params->get("context_handle").string())))
140   {
141     this->context_handle = GSS_C_NO_CONTEXT;
142     if (params->get("context_handle").isString())
143     {
144       key = params->get("context_handle").string();
145       context = GSSContextCache::instance()->retrieve( key.c_str() );
146       this->context_handle = context.getContext();
147     }
148     if (GSS_C_NO_CONTEXT == this->context_handle)
149       throw std::invalid_argument( "Could not find the context_handle." );
150   }
151   
152   // target_name
153   if (! (  params->get("target_name").isNull() ||
154            (params->get("target_name").isString() &&
155             std::string("") == params->get("target_name").string())
156         )
157      )
158   {
159     this->target_name = GSS_C_NO_NAME;
160     if (params->get("target_name").isString())
161     {
162       key = params->get("target_name").string();
163       
164       targetName = GSSNameCache::instance()->retrieve(key);
165       
166       this->target_name = targetName.toGss();
167     }
168     if (GSS_C_NO_NAME == this->target_name)
169       throw std::invalid_argument( "Could not find the target_name" );
170   }
171   
172   // mech_type  
173   if (! ( params->get("mech_type").isNull() ||
174           (
175             params->get("mech_type").isString() &&
176             std::string("") == params->get("mech_type").string()
177           )
178         )
179      )
180   {
181     key.clear();
182     if (params->get("mech_type").isString())
183     {
184       key = params->get("mech_type").string();
185       mechType.setValue(key);
186     }
187     if (GSS_C_NO_OID == this->mechType.toGss() )
188       throw std::invalid_argument( std::string() + "Could not create a mech_type OID from '" + key + "'");
189   }
190   
191   // req_flags
192   if (!params->get("req_flags").isNull() )
193     this->req_flags = (OM_uint32 )params->get("req_flags").integer();
194
195   // time_req
196   if (!params->get("time_req").isNull() )
197     this->time_req = (OM_uint32 )params->get("time_req").integer();
198
199   // input_token
200   if (! (params->get("input_token").isNull() ||
201          (params->get("input_token").isString() &&
202           std::string("") == params->get("input_token").string())))
203   {
204     token = params->get("input_token").string();
205     input_token.value = base64Decode(token.c_str(), &input_token.length);
206   }
207
208   /* Cleanup */
209   
210   /* Return */
211   return true;
212 }
213
214 bool GSSInitSecContext::zeroOut(bool initialized)
215 {
216   /* Error checking */
217   /* Variables */
218   OM_uint32 minor;
219   gss_buffer_desc output;
220   
221   /* Setup */
222   /* Main */
223
224   // Free up existing memory if it's been set.  
225   if (initialized)
226   {
227     if (this->context_handle != NULL)
228       gss_delete_sec_context(&minor, &(this->context_handle), &output);
229     
230     if (this->target_name != NULL)
231       gss_release_name(&minor, &(this->target_name));
232       
233     if (this->output_token.length > 0)
234       gss_release_buffer(&minor, &output_token);
235     
236     if (this->input_token.value) {
237       base64Free(input_token.value);
238       input_token.value = NULL;
239       input_token.length = 0;
240     }
241   }
242
243   // Now set things to reasonable defaults
244   this->retVal = 0;
245   this->minor_status = 0;
246   this->req_flags = 0;
247   this->time_req = 0;
248   this->ret_flags = 0;
249   this->time_rec = 0;
250
251   this->context_handle = GSS_C_NO_CONTEXT;
252   this->target_name = GSS_C_NO_NAME;
253   this->mechType.setValue( (char *)"{ 1 3 6 1 5 5 15 1 1 18 }" );
254   this->input_token.length = 0;
255   this->input_token.value = NULL;
256   this->output_token.length = 0;
257   this->output_token.value = NULL;
258
259   /* Cleanup */
260   /* Return */
261   return(true);
262 }
263
264 JSONObject *GSSInitSecContext::toJSON()
265 {
266   /* Variables */
267   // MRW -- values should be scoped to the class, so execute can set error values?
268   std::string output_str;
269   JSONObject *values = new JSONObject();
270   base64EncodeStr(output_token.value, output_token.length, output_str);
271   
272   /* Error checking */
273   
274   /* Setup */
275   
276   /* Main */
277   values->set("major_status", this->retVal);
278   values->set("minor_status", this->minor_status);
279   values->set("context_handle", this->contextKey.c_str());
280   values->set("actual_mech_type", this->getActualMechType().toString().c_str());
281   values->set("output_token", output_str.c_str());
282   values->set("ret_flags", this->ret_flags);
283   values->set("time_rec", this->time_rec);
284   // MRW -- modify for new error handling
285
286   /* Cleanup */
287   
288   /* Return */
289   return(values);
290 }
291
292 GSSInitSecContext::GSSInitSecContext(
293   JSONObject *params, 
294   init_sec_context_type fn)
295 {
296   zeroOut(false);
297   loadParameters(params);
298   function = fn;
299 }
300
301 GSSInitSecContext::GSSInitSecContext(init_sec_context_type fn)
302 {
303   zeroOut(false);
304   function = fn;
305 }
306