00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "includes.h"
00025
00026 #undef DBGC_CLASS
00027 #define DBGC_CLASS DBGC_AUTH
00028
00029 static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
00030 {
00031 ZERO_STRUCTP(token);
00032
00033 asn1_start_tag(asn1, ASN1_CONTEXT(0));
00034 asn1_start_tag(asn1, ASN1_SEQUENCE(0));
00035
00036 while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
00037 int i;
00038
00039 switch (asn1->data[asn1->ofs]) {
00040
00041 case ASN1_CONTEXT(0):
00042 asn1_start_tag(asn1, ASN1_CONTEXT(0));
00043 asn1_start_tag(asn1, ASN1_SEQUENCE(0));
00044
00045 token->mechTypes = SMB_MALLOC_P(const char *);
00046 for (i = 0; !asn1->has_error &&
00047 0 < asn1_tag_remaining(asn1); i++) {
00048 char *p_oid = NULL;
00049 token->mechTypes =
00050 SMB_REALLOC_ARRAY(token->mechTypes, const char *, i + 2);
00051 if (!token->mechTypes) {
00052 asn1->has_error = True;
00053 return False;
00054 }
00055 asn1_read_OID(asn1, &p_oid);
00056 token->mechTypes[i] = p_oid;
00057 }
00058 token->mechTypes[i] = NULL;
00059
00060 asn1_end_tag(asn1);
00061 asn1_end_tag(asn1);
00062 break;
00063
00064 case ASN1_CONTEXT(1):
00065 asn1_start_tag(asn1, ASN1_CONTEXT(1));
00066 asn1_read_Integer(asn1, &token->reqFlags);
00067 token->reqFlags |= SPNEGO_REQ_FLAG;
00068 asn1_end_tag(asn1);
00069 break;
00070
00071 case ASN1_CONTEXT(2):
00072 asn1_start_tag(asn1, ASN1_CONTEXT(2));
00073 asn1_read_OctetString(asn1, &token->mechToken);
00074 asn1_end_tag(asn1);
00075 break;
00076
00077 case ASN1_CONTEXT(3):
00078 asn1_start_tag(asn1, ASN1_CONTEXT(3));
00079 if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) {
00080 asn1_read_OctetString(asn1,
00081 &token->mechListMIC);
00082 } else {
00083
00084
00085 char *mechListMIC;
00086 asn1_push_tag(asn1, ASN1_SEQUENCE(0));
00087 asn1_push_tag(asn1, ASN1_CONTEXT(0));
00088 asn1_read_GeneralString(asn1, &mechListMIC);
00089 asn1_pop_tag(asn1);
00090 asn1_pop_tag(asn1);
00091
00092 token->mechListMIC =
00093 data_blob(mechListMIC, strlen(mechListMIC));
00094 SAFE_FREE(mechListMIC);
00095 }
00096 asn1_end_tag(asn1);
00097 break;
00098 default:
00099 asn1->has_error = True;
00100 break;
00101 }
00102 }
00103
00104 asn1_end_tag(asn1);
00105 asn1_end_tag(asn1);
00106
00107 return !asn1->has_error;
00108 }
00109
00110 static BOOL write_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
00111 {
00112 asn1_push_tag(asn1, ASN1_CONTEXT(0));
00113 asn1_push_tag(asn1, ASN1_SEQUENCE(0));
00114
00115
00116 if (token->mechTypes && *token->mechTypes) {
00117 int i;
00118
00119 asn1_push_tag(asn1, ASN1_CONTEXT(0));
00120 asn1_push_tag(asn1, ASN1_SEQUENCE(0));
00121 for (i = 0; token->mechTypes[i]; i++) {
00122 asn1_write_OID(asn1, token->mechTypes[i]);
00123 }
00124 asn1_pop_tag(asn1);
00125 asn1_pop_tag(asn1);
00126 }
00127
00128
00129 if (token->reqFlags & SPNEGO_REQ_FLAG) {
00130 int flags = token->reqFlags & ~SPNEGO_REQ_FLAG;
00131
00132 asn1_push_tag(asn1, ASN1_CONTEXT(1));
00133 asn1_write_Integer(asn1, flags);
00134 asn1_pop_tag(asn1);
00135 }
00136
00137
00138 if (token->mechToken.data) {
00139 asn1_push_tag(asn1, ASN1_CONTEXT(2));
00140 asn1_write_OctetString(asn1, token->mechToken.data,
00141 token->mechToken.length);
00142 asn1_pop_tag(asn1);
00143 }
00144
00145
00146 if (token->mechListMIC.data) {
00147 asn1_push_tag(asn1, ASN1_CONTEXT(3));
00148 #if 0
00149
00150 asn1_write_OctetString(asn1, token->mechListMIC.data,
00151 token->mechListMIC.length);
00152 #else
00153
00154
00155 asn1_push_tag(asn1, ASN1_SEQUENCE(0));
00156 asn1_push_tag(asn1, ASN1_CONTEXT(0));
00157 asn1_push_tag(asn1, ASN1_GENERAL_STRING);
00158 asn1_write(asn1, token->mechListMIC.data,
00159 token->mechListMIC.length);
00160 asn1_pop_tag(asn1);
00161 asn1_pop_tag(asn1);
00162 asn1_pop_tag(asn1);
00163 #endif
00164 asn1_pop_tag(asn1);
00165 }
00166
00167 asn1_pop_tag(asn1);
00168 asn1_pop_tag(asn1);
00169
00170 return !asn1->has_error;
00171 }
00172
00173 static BOOL read_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
00174 {
00175 ZERO_STRUCTP(token);
00176
00177 asn1_start_tag(asn1, ASN1_CONTEXT(1));
00178 asn1_start_tag(asn1, ASN1_SEQUENCE(0));
00179
00180 while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) {
00181 switch (asn1->data[asn1->ofs]) {
00182 case ASN1_CONTEXT(0):
00183 asn1_start_tag(asn1, ASN1_CONTEXT(0));
00184 asn1_start_tag(asn1, ASN1_ENUMERATED);
00185 asn1_read_uint8(asn1, &token->negResult);
00186 asn1_end_tag(asn1);
00187 asn1_end_tag(asn1);
00188 break;
00189 case ASN1_CONTEXT(1):
00190 asn1_start_tag(asn1, ASN1_CONTEXT(1));
00191 asn1_read_OID(asn1, &token->supportedMech);
00192 asn1_end_tag(asn1);
00193 break;
00194 case ASN1_CONTEXT(2):
00195 asn1_start_tag(asn1, ASN1_CONTEXT(2));
00196 asn1_read_OctetString(asn1, &token->responseToken);
00197 asn1_end_tag(asn1);
00198 break;
00199 case ASN1_CONTEXT(3):
00200 asn1_start_tag(asn1, ASN1_CONTEXT(3));
00201 asn1_read_OctetString(asn1, &token->mechListMIC);
00202 asn1_end_tag(asn1);
00203 break;
00204 default:
00205 asn1->has_error = True;
00206 break;
00207 }
00208 }
00209
00210 asn1_end_tag(asn1);
00211 asn1_end_tag(asn1);
00212
00213 return !asn1->has_error;
00214 }
00215
00216 static BOOL write_negTokenTarg(ASN1_DATA *asn1, negTokenTarg_t *token)
00217 {
00218 asn1_push_tag(asn1, ASN1_CONTEXT(1));
00219 asn1_push_tag(asn1, ASN1_SEQUENCE(0));
00220
00221 asn1_push_tag(asn1, ASN1_CONTEXT(0));
00222 asn1_write_enumerated(asn1, token->negResult);
00223 asn1_pop_tag(asn1);
00224
00225 if (token->supportedMech) {
00226 asn1_push_tag(asn1, ASN1_CONTEXT(1));
00227 asn1_write_OID(asn1, token->supportedMech);
00228 asn1_pop_tag(asn1);
00229 }
00230
00231 if (token->responseToken.data) {
00232 asn1_push_tag(asn1, ASN1_CONTEXT(2));
00233 asn1_write_OctetString(asn1, token->responseToken.data,
00234 token->responseToken.length);
00235 asn1_pop_tag(asn1);
00236 }
00237
00238 if (token->mechListMIC.data) {
00239 asn1_push_tag(asn1, ASN1_CONTEXT(3));
00240 asn1_write_OctetString(asn1, token->mechListMIC.data,
00241 token->mechListMIC.length);
00242 asn1_pop_tag(asn1);
00243 }
00244
00245 asn1_pop_tag(asn1);
00246 asn1_pop_tag(asn1);
00247
00248 return !asn1->has_error;
00249 }
00250
00251 ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token)
00252 {
00253 ASN1_DATA asn1;
00254 ssize_t ret = -1;
00255
00256 ZERO_STRUCTP(token);
00257 ZERO_STRUCT(asn1);
00258 asn1_load(&asn1, data);
00259
00260 switch (asn1.data[asn1.ofs]) {
00261 case ASN1_APPLICATION(0):
00262 asn1_start_tag(&asn1, ASN1_APPLICATION(0));
00263 asn1_check_OID(&asn1, OID_SPNEGO);
00264 if (read_negTokenInit(&asn1, &token->negTokenInit)) {
00265 token->type = SPNEGO_NEG_TOKEN_INIT;
00266 }
00267 asn1_end_tag(&asn1);
00268 break;
00269 case ASN1_CONTEXT(1):
00270 if (read_negTokenTarg(&asn1, &token->negTokenTarg)) {
00271 token->type = SPNEGO_NEG_TOKEN_TARG;
00272 }
00273 break;
00274 default:
00275 break;
00276 }
00277
00278 if (!asn1.has_error) ret = asn1.ofs;
00279 asn1_free(&asn1);
00280
00281 return ret;
00282 }
00283
00284 ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego)
00285 {
00286 ASN1_DATA asn1;
00287 ssize_t ret = -1;
00288
00289 ZERO_STRUCT(asn1);
00290
00291 switch (spnego->type) {
00292 case SPNEGO_NEG_TOKEN_INIT:
00293 asn1_push_tag(&asn1, ASN1_APPLICATION(0));
00294 asn1_write_OID(&asn1, OID_SPNEGO);
00295 write_negTokenInit(&asn1, &spnego->negTokenInit);
00296 asn1_pop_tag(&asn1);
00297 break;
00298 case SPNEGO_NEG_TOKEN_TARG:
00299 write_negTokenTarg(&asn1, &spnego->negTokenTarg);
00300 break;
00301 default:
00302 asn1.has_error = True;
00303 break;
00304 }
00305
00306 if (!asn1.has_error) {
00307 *blob = data_blob(asn1.data, asn1.length);
00308 ret = asn1.ofs;
00309 }
00310 asn1_free(&asn1);
00311
00312 return ret;
00313 }
00314
00315 BOOL free_spnego_data(SPNEGO_DATA *spnego)
00316 {
00317 BOOL ret = True;
00318
00319 if (!spnego) goto out;
00320
00321 switch(spnego->type) {
00322 case SPNEGO_NEG_TOKEN_INIT:
00323 if (spnego->negTokenInit.mechTypes) {
00324 int i;
00325 for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) {
00326 free(CONST_DISCARD(char *,spnego->negTokenInit.mechTypes[i]));
00327 }
00328 free(spnego->negTokenInit.mechTypes);
00329 }
00330 data_blob_free(&spnego->negTokenInit.mechToken);
00331 data_blob_free(&spnego->negTokenInit.mechListMIC);
00332 break;
00333 case SPNEGO_NEG_TOKEN_TARG:
00334 if (spnego->negTokenTarg.supportedMech) {
00335 free(spnego->negTokenTarg.supportedMech);
00336 }
00337 data_blob_free(&spnego->negTokenTarg.responseToken);
00338 data_blob_free(&spnego->negTokenTarg.mechListMIC);
00339 break;
00340 default:
00341 ret = False;
00342 break;
00343 }
00344 ZERO_STRUCTP(spnego);
00345 out:
00346 return ret;
00347 }