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