Commit an overly-large chunk of work.
[gssweb.git] / json_gssapi / src / commands / GSSCreateSecContextCommand.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 "GSSCreateSecContextCommand.h"
9 #include "GSSException.h"
10 #include <cache/GSSContextCache.h>
11 #include <gssapi.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 typedef OM_uint32 (*init_sec_context)(
16     OM_uint32 *,        /* minor_status */
17     gss_cred_id_t,      /* claimant_cred_handle */
18     gss_ctx_id_t *,     /* context_handle */
19     gss_name_t,         /* target_name */
20     gss_OID,            /* mech_type (used to be const) */
21     OM_uint32,          /* req_flags */
22     OM_uint32,          /* time_req */
23     gss_channel_bindings_t,     /* input_chan_bindings */
24     gss_buffer_t,       /* input_token */
25     gss_OID *,          /* actual_mech_type */
26     gss_buffer_t,       /* output_token */
27     OM_uint32 *,        /* ret_flags */
28     OM_uint32 *         /* time_req */
29 );
30
31 /* Helper function - import the OID from a string */
32 static gss_OID str_to_oid(const char *mech_type_str = NULL)
33 {
34   /* Variables */
35   gss_buffer_desc gssbuffOID;
36   gss_OID gssoidTargetOID;
37   OM_uint32 major;
38   OM_uint32 minor;
39   
40   /* Error checking */
41   if (mech_type_str == NULL ||
42       *mech_type_str == 0)
43     return NULL;
44   
45   /* Setup */
46   /* Main */
47   gssbuffOID.value = (void *)(mech_type_str);
48   gssbuffOID.length = strlen(mech_type_str);
49   major = gss_str_to_oid(&minor, 
50                          &gssbuffOID, 
51                          &gssoidTargetOID);
52   if (major != GSS_S_COMPLETE)
53     throw GSSException("Error converting string to OID", major, minor);
54
55   /* Cleanup */
56   
57   /* Return */
58   return gssoidTargetOID;
59 }
60
61 void
62 GSSCreateSecContextCommand::execute()
63 {
64   /* Variables */
65   init_sec_context fn = (init_sec_context)function;
66   
67   /* Error checking */
68   
69   /* Setup */
70   if (output_token.length > 0)
71     retVal = gss_release_buffer(&minor_status, &output_token);
72   
73   /* Main */
74   
75   retVal = fn(
76     &minor_status,
77     GSS_C_NO_CREDENTIAL,
78     &context_handle,
79     target_name,
80     mech_type,
81     req_flags,
82     time_req,
83     GSS_C_NO_CHANNEL_BINDINGS,
84     &input_token,
85     &actual_mech_type,
86     &output_token,
87     &ret_flags,
88     &time_rec);
89   
90   context.setContext(context_handle, true);
91   contextKey = GSSContextCache::instance()->store(context);
92   
93   /* Cleanup */
94   
95   /* Return */
96 }
97
98 const char* GSSCreateSecContextCommand::getTargetDisplayName()
99 {
100   /* Variables */
101   gss_buffer_desc output_name;
102   gss_OID output_type;
103   OM_uint32 major, minor;
104   const char *ret;
105   
106   /* error checking */
107   
108   /* Setup */
109   
110   /* Main */
111   major = gss_display_name(&minor, target_name, &output_name, &output_type);
112   if (major == GSS_S_COMPLETE)
113     ret = (const char *)output_name.value;
114   else
115     ret = NULL;
116   
117   /* cleanup */
118   
119   /* return */
120   return( ret );
121 }
122
123 const char* GSSCreateSecContextCommand::getActualMechType()
124 {
125   return(this->oidToStr(this->actual_mech_type));
126 }
127
128 const char* GSSCreateSecContextCommand::getMechType()
129 {
130   return(this->oidToStr(this->mech_type));
131 }
132
133 const char* GSSCreateSecContextCommand::oidToStr(gss_OID oid)
134 {
135   gss_buffer_desc output;
136   OM_uint32 major, minor;
137   const char *retVal;
138
139   /* error checking */
140   if (oid == NULL)
141     return NULL;
142
143   /* Setup */  
144   
145   /* main */
146   major = gss_oid_to_str(&minor, oid, &output);
147   if (major == GSS_S_COMPLETE)
148     retVal = (const char *)output.value;
149   else
150     retVal = NULL;
151   
152   /* cleanup */
153   
154   /* return */
155   return( retVal );
156 }
157
158 bool GSSCreateSecContextCommand::loadParameters(JSONObject *params)
159 {
160   /* Variables */
161   OM_uint32 major, minor;
162   gss_buffer_desc gssbuffTargetName;
163   const char *buffer;
164   
165   /* Error checking */
166   
167   /* Setup */
168   // Should I zeroOut?
169   
170   /* Main processing */
171   // Easy stuff(*params)
172   this->time_req = (OM_uint32)( (*params)["arguments"]["time_req"].integer() );
173   this->req_flags = (OM_uint32)( (*params)["arguments"]["req_flags"].integer() );
174   
175   // context_handle
176   //   -- just treat the value passed in as correct.
177   context_handle = (gss_ctx_id_t)( (*params)["arguments"]["context_handle"].integer() );
178   
179   // target_name
180   buffer = (*params)["arguments"]["target_name"].string();
181   if (buffer != NULL && *buffer != 0)
182   {
183     gssbuffTargetName.value = (void *)buffer;
184     gssbuffTargetName.length = strlen( buffer );
185     
186     major = gss_import_name(&minor, 
187                             &gssbuffTargetName, 
188                             GSS_C_NO_OID, 
189                             &target_name);
190     if (major != GSS_S_COMPLETE)
191       throw GSSException("Error importing target_name", major, minor);
192   }
193   
194   // mech_type  
195   mech_type = str_to_oid( (*params)["arguments"]["mech_type"].string() );
196   
197   // input_token
198   buffer = (*params)["arguments"]["input_token"].string();
199   if (buffer != NULL && *buffer != 0)
200   {
201     this->input_token.value = (void *)buffer;
202     this->input_token.length = strlen(buffer);
203   }
204   
205   /* Cleanup */
206   
207   
208   /* Return */
209   return true;
210 }
211
212 bool GSSCreateSecContextCommand::zeroOut(bool initialized)
213 {
214   /* Error checking */
215   /* Variables */
216   OM_uint32 minor;
217   gss_buffer_desc output;
218   
219   /* Setup */
220   /* Main */
221
222   // Free up existing memory if it's been set.  
223   if (initialized)
224   {
225     if (this->context_handle != NULL)
226       gss_delete_sec_context(&minor, &(this->context_handle), &output);
227     
228     if (this->target_name != NULL)
229       gss_release_name(&minor, &(this->target_name));
230       
231     if (mech_type != NULL)
232       gss_release_oid(&minor, &(this->mech_type));
233     
234     if (this->actual_mech_type != NULL)
235       gss_release_oid(&minor, &(this->actual_mech_type));
236     
237     if (this->output_token.length > 0)
238       gss_release_buffer(&minor, &output_token);
239     
240     if (this->input_token.length > 0)
241       gss_release_buffer(&minor, &input_token);
242   }
243
244   // Now set things to reasonable defaults
245   this->retVal = 0;
246   this->minor_status = 0;
247   this->req_flags = 0;
248   this->time_req = 0;
249   this->ret_flags = 0;
250   this->time_rec = 0;
251
252   this->context_handle = GSS_C_NO_CONTEXT;
253   this->target_name = GSS_C_NO_NAME;
254   mech_type = str_to_oid( "{ 1 2 840 113554 1 2 1 4 }" );
255   this->input_token.length = 0;
256   this->input_token.value = NULL;
257   this->actual_mech_type = GSS_C_NO_OID;
258   this->output_token.length = 0;
259   this->output_token.value = NULL;
260
261   /* Cleanup */
262   /* Return */
263   return(true);
264 }
265
266 JSONObject *GSSCreateSecContextCommand::toJSON()
267 {
268   /* Variables */
269   JSONObject *ret = new JSONObject();
270   JSONObject *values = new JSONObject();
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());
281   values->set("output_token", (const char *)this->output_token.value);
282   values->set("ret_flags", this->ret_flags);
283   values->set("time_rec", this->time_rec);
284   ret->set("command", "gss_init_sec_context");
285   ret->set("return_values", *values);
286   
287   /* Cleanup */
288   
289   /* Return */
290   return(ret);
291 }
292
293 GSSCreateSecContextCommand::GSSCreateSecContextCommand(
294   JSONObject *params, 
295   void *fn) : GSSCommand(params)
296 {
297   zeroOut(false);
298   loadParameters(params);
299   function = fn;
300 }
301
302 GSSCreateSecContextCommand::GSSCreateSecContextCommand(void *fn)
303 {
304   zeroOut(false);
305   function = fn;
306 }
307