0f312b97aa81da6cb68a4f7513993e5442bc1bb4
[gssweb.git] / json_gssapi / src / commands / GSSInitSecContext.cpp
1 /*
2  * Copyright (c) 2014 <copyright holder> <email>
3  * 
4  * For license details, see the LICENSE file in the root of this project.
5  * 
6  */
7
8 #include "GSSInitSecContext.h"
9 #include "GSSException.h"
10 #include <cache/GSSContextCache.h>
11 #include <cache/GSSNameCache.h>
12 #include <datamodel/GSSName.h>
13 #include <gssapi.h>
14 #include <stdexcept>
15 #include <stdlib.h>
16 #include <string.h>
17
18 typedef OM_uint32 (*init_sec_context)(
19     OM_uint32 *,        /* minor_status */
20     gss_cred_id_t,      /* claimant_cred_handle */
21     gss_ctx_id_t *,     /* context_handle */
22     gss_name_t,         /* target_name */
23     gss_OID,            /* mech_type (used to be const) */
24     OM_uint32,          /* req_flags */
25     OM_uint32,          /* time_req */
26     gss_channel_bindings_t,     /* input_chan_bindings */
27     gss_buffer_t,       /* input_token */
28     gss_OID *,          /* actual_mech_type */
29     gss_buffer_t,       /* output_token */
30     OM_uint32 *,        /* ret_flags */
31     OM_uint32 *         /* time_req */
32 );
33
34 void
35 GSSInitSecContext::execute()
36 {
37   /* Variables */
38   init_sec_context fn = (init_sec_context)function;
39   gss_OID actual_mech_type;
40   
41   /* Error checking */
42   
43   /* Setup */
44   if (output_token.length > 0)
45     retVal = gss_release_buffer(&minor_status, &output_token);
46
47   /* Main */
48   retVal = fn(
49     &minor_status,
50     GSS_C_NO_CREDENTIAL,
51     &context_handle,
52     targetName.toGss(),
53     mechType.toGss(),
54     req_flags,
55     time_req,
56     GSS_C_NO_CHANNEL_BINDINGS,
57     &input_token,
58     &actual_mech_type,
59     &output_token,
60     &ret_flags,
61     &time_rec);
62   
63   if ( GSS_ERROR(this->retVal) )
64   {
65     std::string errMsg;
66     errMsg += "Cannot init_sec_context: ";
67     throw GSSException(errMsg.c_str(), this->retVal, this->minor_status, mechType.toGss());
68   }
69   
70   actualMechType.setValue(actual_mech_type);
71   
72   context.setContext(context_handle, true);
73   contextKey = GSSContextCache::instance()->store(context);
74   
75   /* Cleanup */
76   
77   /* Return */
78 }
79
80 const char* GSSInitSecContext::getTargetDisplayName()
81 {
82   /* Variables */
83   gss_buffer_desc output_name;
84   gss_OID output_type;
85   OM_uint32 major, minor;
86   const char *ret;
87   
88   /* error checking */
89   
90   /* Setup */
91   
92   /* Main */
93   major = gss_display_name(&minor, target_name, &output_name, &output_type);
94   if (major == GSS_S_COMPLETE)
95     ret = (const char *)output_name.value;
96   else
97     ret = NULL;
98   
99   /* cleanup */
100   
101   /* return */
102   return( ret );
103 }
104
105 bool GSSInitSecContext::loadParameters(JSONObject *params)
106 {
107   /* Variables */
108   std::string key;
109   
110   /* Error checking */
111   if ( params->isNull() )
112     return true;
113   
114   /* Setup */
115   // Should I zeroOut?
116   
117   /* Main processing */
118   // Easy stuff(*params)
119   if ( !params->get("time_req").isNull() )
120     this->time_req = params->get("time_req").integer();
121   
122   if ( !params->get("req_flags").isNull() )
123     this->req_flags = params->get("req_flags").integer();
124   
125   // context_handle
126   if ( ! params->get("context_handle").isNull() )
127   {
128     this->context_handle = GSS_C_NO_CONTEXT;
129     if (params->get("context_handle").isString())
130     {
131       key = params->get("context_handle").string();
132       context = GSSContextCache::instance()->retrieve( key.c_str() );
133       this->context_handle = context.getContext();
134     }
135     if (GSS_C_NO_CONTEXT == this->context_handle)
136       throw std::invalid_argument( "Could not find the context_handle." );
137   }
138   
139   // target_name
140   if ( ! params->get("target_name").isNull() )
141   {
142     this->target_name = GSS_C_NO_NAME;
143     if (params->get("target_name").isString())
144     {
145       key = params->get("target_name").string();
146       
147       targetName = GSSNameCache::instance()->retrieve(key);
148       
149       this->target_name = targetName.toGss();
150     }
151     if (GSS_C_NO_NAME == this->target_name)
152       throw std::invalid_argument( "Could not find the target_name" );
153   }
154   
155   // mech_type  
156   if ( ! params->get("mech_type").isNull() )
157   {
158     key.clear();
159     if (params->get("mech_type").isString())
160     {
161       key = params->get("mech_type").string();
162       mechType.setValue(key);
163     }
164     if (GSS_C_NO_OID == this->mechType.toGss() )
165       throw std::invalid_argument( std::string() + "Could not create a mech_type OID from '" + key + "'");
166   }
167   
168   // input_token
169   if ( ! params->get("input_token").isNull() )
170   {
171     key = params->get("input_token").string();
172     this->input_token.value = (void *)key.c_str();
173     this->input_token.length = key.length();
174   }
175
176   /* Cleanup */
177   
178   
179   /* Return */
180   return true;
181 }
182
183 bool GSSInitSecContext::zeroOut(bool initialized)
184 {
185   /* Error checking */
186   /* Variables */
187   OM_uint32 minor;
188   gss_buffer_desc output;
189   
190   /* Setup */
191   /* Main */
192
193   // Free up existing memory if it's been set.  
194   if (initialized)
195   {
196     if (this->context_handle != NULL)
197       gss_delete_sec_context(&minor, &(this->context_handle), &output);
198     
199     if (this->target_name != NULL)
200       gss_release_name(&minor, &(this->target_name));
201       
202     if (this->output_token.length > 0)
203       gss_release_buffer(&minor, &output_token);
204     
205     if (this->input_token.length > 0)
206       gss_release_buffer(&minor, &input_token);
207   }
208
209   // Now set things to reasonable defaults
210   this->retVal = 0;
211   this->minor_status = 0;
212   this->req_flags = 0;
213   this->time_req = 0;
214   this->ret_flags = 0;
215   this->time_rec = 0;
216
217   this->context_handle = GSS_C_NO_CONTEXT;
218   this->target_name = GSS_C_NO_NAME;
219   this->mechType.setValue( (char *)"{ 1 3 6 1 5 5 15 1 1 18 }" );
220   this->input_token.length = 0;
221   this->input_token.value = NULL;
222   this->output_token.length = 0;
223   this->output_token.value = NULL;
224
225   /* Cleanup */
226   /* Return */
227   return(true);
228 }
229
230 JSONObject *GSSInitSecContext::toJSON()
231 {
232   /* Variables */
233   JSONObject *values = new JSONObject();
234   
235   /* Error checking */
236   
237   /* Setup */
238   
239   /* Main */
240   values->set("major_status", this->retVal);
241   values->set("minor_status", this->minor_status);
242   values->set("context_handle", this->contextKey.c_str());
243   values->set("actual_mech_type", this->getActualMechType().toString().c_str());
244   values->set("output_token", (const char *)this->output_token.value);
245   values->set("ret_flags", this->ret_flags);
246   values->set("time_rec", this->time_rec);
247   
248   /* Cleanup */
249   
250   /* Return */
251   return(values);
252 }
253
254 GSSInitSecContext::GSSInitSecContext(
255   JSONObject *params, 
256   void *fn) : GSSCommand(params)
257 {
258   zeroOut(false);
259   loadParameters(params);
260   function = fn;
261 }
262
263 GSSInitSecContext::GSSInitSecContext(void *fn)
264 {
265   zeroOut(false);
266   function = fn;
267 }
268