root/source4/auth/gensec/gensec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gensec_security_all
  2. gensec_security_ops_enabled
  3. gensec_use_kerberos_mechs
  4. gensec_security_mechs
  5. gensec_security_by_authtype
  6. gensec_security_by_oid
  7. gensec_security_by_sasl_name
  8. gensec_security_by_name
  9. gensec_security_by_sasl_list
  10. gensec_security_by_oid_list
  11. gensec_security_oids_from_ops
  12. gensec_security_oids_from_ops_wrapped
  13. gensec_security_oids
  14. gensec_start
  15. gensec_subcontext_start
  16. gensec_client_start
  17. gensec_server_start
  18. gensec_start_mech
  19. gensec_start_mech_by_authtype
  20. gensec_get_name_by_authtype
  21. gensec_get_name_by_oid
  22. gensec_start_mech_by_ops
  23. gensec_start_mech_by_oid
  24. gensec_start_mech_by_sasl_name
  25. gensec_start_mech_by_sasl_list
  26. gensec_start_mech_by_name
  27. gensec_unseal_packet
  28. gensec_check_packet
  29. gensec_seal_packet
  30. gensec_sign_packet
  31. gensec_sig_size
  32. gensec_max_wrapped_size
  33. gensec_max_input_size
  34. gensec_wrap
  35. gensec_unwrap
  36. gensec_session_key
  37. gensec_session_info
  38. gensec_update
  39. gensec_update_async_timed_handler
  40. gensec_update_send
  41. gensec_update_recv
  42. gensec_want_feature
  43. gensec_have_feature
  44. gensec_set_credentials
  45. gensec_get_credentials
  46. gensec_set_target_service
  47. gensec_get_target_service
  48. gensec_set_target_hostname
  49. gensec_get_target_hostname
  50. gensec_set_my_addr
  51. gensec_set_peer_addr
  52. gensec_get_my_addr
  53. gensec_get_peer_addr
  54. gensec_set_target_principal
  55. gensec_get_target_principal
  56. gensec_register
  57. gensec_interface_version
  58. sort_gensec
  59. gensec_setting_int
  60. gensec_setting_bool
  61. gensec_init

   1 /* 
   2    Unix SMB/CIFS implementation.
   3  
   4    Generic Authentication Interface
   5 
   6    Copyright (C) Andrew Tridgell 2003
   7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2006
   8    
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 3 of the License, or
  12    (at your option) any later version.
  13    
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18    
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  21 */
  22 
  23 #include "includes.h"
  24 #include "auth/auth.h"
  25 #include "lib/events/events.h"
  26 #include "librpc/rpc/dcerpc.h"
  27 #include "auth/credentials/credentials.h"
  28 #include "auth/gensec/gensec.h"
  29 #include "auth/gensec/gensec_proto.h"
  30 #include "param/param.h"
  31 
  32 /* the list of currently registered GENSEC backends */
  33 static struct gensec_security_ops **generic_security_ops;
  34 static int gensec_num_backends;
  35 
  36 /* Return all the registered mechs.  Don't modify the return pointer,
  37  * but you may talloc_reference it if convient */
  38 _PUBLIC_ struct gensec_security_ops **gensec_security_all(void)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         return generic_security_ops;
  41 }
  42 
  43 bool gensec_security_ops_enabled(struct gensec_security_ops *ops, 
     /* [<][>][^][v][top][bottom][index][help] */
  44                                  struct loadparm_context *lp_ctx)
  45 {
  46         return lp_parm_bool(lp_ctx, NULL, "gensec", ops->name, ops->enabled);
  47 }
  48 
  49 /* Sometimes we want to force only kerberos, sometimes we want to
  50  * force it's avoidance.  The old list could be either
  51  * gensec_security_all(), or from cli_credentials_gensec_list() (ie,
  52  * an existing list we have trimmed down) */
  53 
  54 _PUBLIC_ struct gensec_security_ops **gensec_use_kerberos_mechs(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
  55                                                        struct gensec_security_ops **old_gensec_list, 
  56                                                        struct cli_credentials *creds)
  57 {
  58         struct gensec_security_ops **new_gensec_list;
  59         int i, j, num_mechs_in;
  60         enum credentials_use_kerberos use_kerberos = CRED_AUTO_USE_KERBEROS;
  61 
  62         if (creds) {
  63                 use_kerberos = cli_credentials_get_kerberos_state(creds);
  64         }
  65 
  66         if (use_kerberos == CRED_AUTO_USE_KERBEROS) {
  67                 if (!talloc_reference(mem_ctx, old_gensec_list)) {
  68                         return NULL;
  69                 }
  70                 return old_gensec_list;
  71         }
  72 
  73         for (num_mechs_in=0; old_gensec_list && old_gensec_list[num_mechs_in]; num_mechs_in++) {
  74                 /* noop */
  75         }
  76 
  77         new_gensec_list = talloc_array(mem_ctx, struct gensec_security_ops *, num_mechs_in + 1);
  78         if (!new_gensec_list) {
  79                 return NULL;
  80         }
  81 
  82         j = 0;
  83         for (i=0; old_gensec_list && old_gensec_list[i]; i++) {
  84                 int oid_idx;
  85 
  86                 for (oid_idx = 0; old_gensec_list[i]->oid && old_gensec_list[i]->oid[oid_idx]; oid_idx++) {
  87                         if (strcmp(old_gensec_list[i]->oid[oid_idx], GENSEC_OID_SPNEGO) == 0) {
  88                                 new_gensec_list[j] = old_gensec_list[i];
  89                                 j++;
  90                                 break;
  91                         }
  92                 }
  93                 switch (use_kerberos) {
  94                 case CRED_DONT_USE_KERBEROS:
  95                         if (old_gensec_list[i]->kerberos == false) {
  96                                 new_gensec_list[j] = old_gensec_list[i];
  97                                 j++;
  98                         }
  99                         break;
 100                 case CRED_MUST_USE_KERBEROS:
 101                         if (old_gensec_list[i]->kerberos == true) {
 102                                 new_gensec_list[j] = old_gensec_list[i];
 103                                 j++;
 104                         }
 105                         break;
 106                 default:
 107                         /* Can't happen or invalid parameter */
 108                         return NULL;
 109                 }
 110         }
 111         new_gensec_list[j] = NULL; 
 112         
 113         return new_gensec_list;
 114 }
 115 
 116 struct gensec_security_ops **gensec_security_mechs(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 117                                                    TALLOC_CTX *mem_ctx) 
 118 {
 119         struct gensec_security_ops **backends;
 120         backends = gensec_security_all();
 121         if (!gensec_security) {
 122                 if (!talloc_reference(mem_ctx, backends)) {
 123                         return NULL;
 124                 }
 125                 return backends;
 126         } else {
 127                 struct cli_credentials *creds = gensec_get_credentials(gensec_security);
 128                 if (!creds) {
 129                         if (!talloc_reference(mem_ctx, backends)) {
 130                                 return NULL;
 131                         }
 132                         return backends;
 133                 }
 134                 return gensec_use_kerberos_mechs(mem_ctx, backends, creds);
 135         }
 136 }
 137 
 138 static const struct gensec_security_ops *gensec_security_by_authtype(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 139                                                                      uint8_t auth_type)
 140 {
 141         int i;
 142         struct gensec_security_ops **backends;
 143         const struct gensec_security_ops *backend;
 144         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
 145         if (!mem_ctx) {
 146                 return NULL;
 147         }
 148         backends = gensec_security_mechs(gensec_security, mem_ctx);
 149         for (i=0; backends && backends[i]; i++) {
 150                 if (!gensec_security_ops_enabled(backends[i], 
 151                                                                                          gensec_security->settings->lp_ctx))
 152                     continue;
 153                 if (backends[i]->auth_type == auth_type) {
 154                         backend = backends[i];
 155                         talloc_free(mem_ctx);
 156                         return backend;
 157                 }
 158         }
 159         talloc_free(mem_ctx);
 160 
 161         return NULL;
 162 }
 163 
 164 const struct gensec_security_ops *gensec_security_by_oid(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 165                                                          const char *oid_string)
 166 {
 167         int i, j;
 168         struct gensec_security_ops **backends;
 169         const struct gensec_security_ops *backend;
 170         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
 171         if (!mem_ctx) {
 172                 return NULL;
 173         }
 174         backends = gensec_security_mechs(gensec_security, mem_ctx);
 175         for (i=0; backends && backends[i]; i++) {
 176                 if (gensec_security != NULL && 
 177                                 !gensec_security_ops_enabled(backends[i], 
 178                                                                                          gensec_security->settings->lp_ctx))
 179                     continue;
 180                 if (backends[i]->oid) {
 181                         for (j=0; backends[i]->oid[j]; j++) { 
 182                                 if (backends[i]->oid[j] &&
 183                                     (strcmp(backends[i]->oid[j], oid_string) == 0)) {
 184                                         backend = backends[i];
 185                                         talloc_free(mem_ctx);
 186                                         return backend;
 187                                 }
 188                         }
 189                 }
 190         }
 191         talloc_free(mem_ctx);
 192 
 193         return NULL;
 194 }
 195 
 196 const struct gensec_security_ops *gensec_security_by_sasl_name(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 197                                                                const char *sasl_name)
 198 {
 199         int i;
 200         struct gensec_security_ops **backends;
 201         const struct gensec_security_ops *backend;
 202         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
 203         if (!mem_ctx) {
 204                 return NULL;
 205         }
 206         backends = gensec_security_mechs(gensec_security, mem_ctx);
 207         for (i=0; backends && backends[i]; i++) {
 208                 if (!gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
 209                     continue;
 210                 if (backends[i]->sasl_name 
 211                     && (strcmp(backends[i]->sasl_name, sasl_name) == 0)) {
 212                         backend = backends[i];
 213                         talloc_free(mem_ctx);
 214                         return backend;
 215                 }
 216         }
 217         talloc_free(mem_ctx);
 218 
 219         return NULL;
 220 }
 221 
 222 static const struct gensec_security_ops *gensec_security_by_name(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 223                                                                  const char *name)
 224 {
 225         int i;
 226         struct gensec_security_ops **backends;
 227         const struct gensec_security_ops *backend;
 228         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
 229         if (!mem_ctx) {
 230                 return NULL;
 231         }
 232         backends = gensec_security_mechs(gensec_security, mem_ctx);
 233         for (i=0; backends && backends[i]; i++) {
 234                 if (gensec_security != NULL && 
 235                                 !gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
 236                     continue;
 237                 if (backends[i]->name 
 238                     && (strcmp(backends[i]->name, name) == 0)) {
 239                         backend = backends[i];
 240                         talloc_free(mem_ctx);
 241                         return backend;
 242                 }
 243         }
 244         talloc_free(mem_ctx);
 245         return NULL;
 246 }
 247 
 248 /**
 249  * Return a unique list of security subsystems from those specified in
 250  * the list of SASL names.   
 251  *
 252  * Use the list of enabled GENSEC mechanisms from the credentials
 253  * attached to the gensec_security, and return in our preferred order.
 254  */
 255 
 256 const struct gensec_security_ops **gensec_security_by_sasl_list(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 257                                                                 TALLOC_CTX *mem_ctx, 
 258                                                                 const char **sasl_names)
 259 {
 260         const struct gensec_security_ops **backends_out;
 261         struct gensec_security_ops **backends;
 262         int i, k, sasl_idx;
 263         int num_backends_out = 0;
 264 
 265         if (!sasl_names) {
 266                 return NULL;
 267         }
 268 
 269         backends = gensec_security_mechs(gensec_security, mem_ctx);
 270 
 271         backends_out = talloc_array(mem_ctx, const struct gensec_security_ops *, 1);
 272         if (!backends_out) {
 273                 return NULL;
 274         }
 275         backends_out[0] = NULL;
 276 
 277         /* Find backends in our preferred order, by walking our list,
 278          * then looking in the supplied list */
 279         for (i=0; backends && backends[i]; i++) {
 280                 if (gensec_security != NULL &&
 281                                 !gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
 282                     continue;
 283                 for (sasl_idx = 0; sasl_names[sasl_idx]; sasl_idx++) {
 284                         if (!backends[i]->sasl_name ||
 285                             !(strcmp(backends[i]->sasl_name, 
 286                                      sasl_names[sasl_idx]) == 0)) {
 287                                 continue;
 288                         }
 289                         
 290                         for (k=0; backends_out[k]; k++) {
 291                                 if (backends_out[k] == backends[i]) {
 292                                         break;
 293                                 }
 294                         }
 295                         
 296                         if (k < num_backends_out) {
 297                                 /* already in there */
 298                                 continue;
 299                         }
 300                         
 301                         backends_out = talloc_realloc(mem_ctx, backends_out, 
 302                                                       const struct gensec_security_ops *, 
 303                                                       num_backends_out + 2);
 304                         if (!backends_out) {
 305                                 return NULL;
 306                         }
 307                         
 308                         backends_out[num_backends_out] = backends[i];
 309                         num_backends_out++;
 310                         backends_out[num_backends_out] = NULL;
 311                 }
 312         }
 313         return backends_out;
 314 }
 315 
 316 /**
 317  * Return a unique list of security subsystems from those specified in
 318  * the OID list.  That is, where two OIDs refer to the same module,
 319  * return that module only once. 
 320  *
 321  * Use the list of enabled GENSEC mechanisms from the credentials
 322  * attached to the gensec_security, and return in our preferred order.
 323  */
 324 
 325 const struct gensec_security_ops_wrapper *gensec_security_by_oid_list(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 326                                                                       TALLOC_CTX *mem_ctx, 
 327                                                                       const char **oid_strings,
 328                                                                       const char *skip)
 329 {
 330         struct gensec_security_ops_wrapper *backends_out;
 331         struct gensec_security_ops **backends;
 332         int i, j, k, oid_idx;
 333         int num_backends_out = 0;
 334 
 335         if (!oid_strings) {
 336                 return NULL;
 337         }
 338 
 339         backends = gensec_security_mechs(gensec_security, gensec_security);
 340 
 341         backends_out = talloc_array(mem_ctx, struct gensec_security_ops_wrapper, 1);
 342         if (!backends_out) {
 343                 return NULL;
 344         }
 345         backends_out[0].op = NULL;
 346         backends_out[0].oid = NULL;
 347 
 348         /* Find backends in our preferred order, by walking our list,
 349          * then looking in the supplied list */
 350         for (i=0; backends && backends[i]; i++) {
 351                 if (gensec_security != NULL && 
 352                                 !gensec_security_ops_enabled(backends[i], gensec_security->settings->lp_ctx))
 353                     continue;
 354                 if (!backends[i]->oid) {
 355                         continue;
 356                 }
 357                 for (oid_idx = 0; oid_strings[oid_idx]; oid_idx++) {
 358                         if (strcmp(oid_strings[oid_idx], skip) == 0) {
 359                                 continue;
 360                         }
 361 
 362                         for (j=0; backends[i]->oid[j]; j++) { 
 363                                 if (!backends[i]->oid[j] ||
 364                                     !(strcmp(backends[i]->oid[j], 
 365                                             oid_strings[oid_idx]) == 0)) {
 366                                         continue;
 367                                 }
 368                                 
 369                                 for (k=0; backends_out[k].op; k++) {
 370                                         if (backends_out[k].op == backends[i]) {
 371                                                 break;
 372                                         }
 373                                 }
 374                                 
 375                                 if (k < num_backends_out) {
 376                                         /* already in there */
 377                                         continue;
 378                                 }
 379 
 380                                 backends_out = talloc_realloc(mem_ctx, backends_out, 
 381                                                               struct gensec_security_ops_wrapper, 
 382                                                               num_backends_out + 2);
 383                                 if (!backends_out) {
 384                                         return NULL;
 385                                 }
 386                                 
 387                                 backends_out[num_backends_out].op = backends[i];
 388                                 backends_out[num_backends_out].oid = backends[i]->oid[j];
 389                                 num_backends_out++;
 390                                 backends_out[num_backends_out].op = NULL;
 391                                 backends_out[num_backends_out].oid = NULL;
 392                         }
 393                 }
 394         }
 395         return backends_out;
 396 }
 397 
 398 /**
 399  * Return OIDS from the security subsystems listed
 400  */
 401 
 402 const char **gensec_security_oids_from_ops(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 403                                                                                    TALLOC_CTX *mem_ctx, 
 404                                            struct gensec_security_ops **ops,                               
 405                                            const char *skip) 
 406 {
 407         int i;
 408         int j = 0;
 409         int k;
 410         const char **oid_list;
 411         if (!ops) {
 412                 return NULL;
 413         }
 414         oid_list = talloc_array(mem_ctx, const char *, 1);
 415         if (!oid_list) {
 416                 return NULL;
 417         }
 418         
 419         for (i=0; ops && ops[i]; i++) {
 420                 if (gensec_security != NULL && 
 421                         !gensec_security_ops_enabled(ops[i], gensec_security->settings->lp_ctx)) {
 422                         continue;
 423                 }
 424                 if (!ops[i]->oid) {
 425                         continue;
 426                 }
 427                 
 428                 for (k = 0; ops[i]->oid[k]; k++) {
 429                         if (skip && strcmp(skip, ops[i]->oid[k])==0) {
 430                         } else {
 431                                 oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
 432                                 if (!oid_list) {
 433                                         return NULL;
 434                                 }
 435                                 oid_list[j] = ops[i]->oid[k];
 436                                 j++;
 437                         }
 438                 }
 439         }
 440         oid_list[j] = NULL;
 441         return oid_list;
 442 }
 443 
 444 
 445 /**
 446  * Return OIDS from the security subsystems listed
 447  */
 448 
 449 const char **gensec_security_oids_from_ops_wrapped(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 450                                                    const struct gensec_security_ops_wrapper *wops)
 451 {
 452         int i;
 453         int j = 0;
 454         int k;
 455         const char **oid_list;
 456         if (!wops) {
 457                 return NULL;
 458         }
 459         oid_list = talloc_array(mem_ctx, const char *, 1);
 460         if (!oid_list) {
 461                 return NULL;
 462         }
 463         
 464         for (i=0; wops[i].op; i++) {
 465                 if (!wops[i].op->oid) {
 466                         continue;
 467                 }
 468                 
 469                 for (k = 0; wops[i].op->oid[k]; k++) {
 470                         oid_list = talloc_realloc(mem_ctx, oid_list, const char *, j + 2);
 471                         if (!oid_list) {
 472                                 return NULL;
 473                         }
 474                         oid_list[j] = wops[i].op->oid[k];
 475                         j++;
 476                 }
 477         }
 478         oid_list[j] = NULL;
 479         return oid_list;
 480 }
 481 
 482 
 483 /**
 484  * Return all the security subsystems currently enabled on a GENSEC context.
 485  * 
 486  * This is taken from a list attached to the cli_credentials, and
 487  * skips the OID in 'skip'.  (Typically the SPNEGO OID)
 488  * 
 489  */
 490 
 491 const char **gensec_security_oids(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 492                                   TALLOC_CTX *mem_ctx, 
 493                                   const char *skip) 
 494 {
 495         struct gensec_security_ops **ops
 496                 = gensec_security_mechs(gensec_security, mem_ctx);
 497         return gensec_security_oids_from_ops(gensec_security, mem_ctx, ops, skip);
 498 }
 499 
 500 
 501 
 502 /**
 503   Start the GENSEC system, returning a context pointer.
 504   @param mem_ctx The parent TALLOC memory context.
 505   @param gensec_security Returned GENSEC context pointer.
 506   @note  The mem_ctx is only a parent and may be NULL.
 507 */
 508 static NTSTATUS gensec_start(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 509                              struct tevent_context *ev,
 510                              struct gensec_settings *settings,
 511                              struct auth_context *auth_context,
 512                              struct gensec_security **gensec_security)
 513 {
 514         if (ev == NULL) {
 515                 DEBUG(0, ("No event context available!\n"));
 516                 return NT_STATUS_INTERNAL_ERROR;
 517         }
 518 
 519         (*gensec_security) = talloc(mem_ctx, struct gensec_security);
 520         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
 521 
 522         (*gensec_security)->ops = NULL;
 523         (*gensec_security)->private_data = NULL;
 524 
 525         ZERO_STRUCT((*gensec_security)->target);
 526         ZERO_STRUCT((*gensec_security)->peer_addr);
 527         ZERO_STRUCT((*gensec_security)->my_addr);
 528 
 529         (*gensec_security)->subcontext = false;
 530         (*gensec_security)->want_features = 0;
 531 
 532         (*gensec_security)->event_ctx = ev;
 533         SMB_ASSERT(settings->lp_ctx != NULL);
 534         (*gensec_security)->settings = talloc_reference(*gensec_security, settings);
 535         (*gensec_security)->auth_context = talloc_reference(*gensec_security, auth_context);
 536 
 537         return NT_STATUS_OK;
 538 }
 539 
 540 /** 
 541  * Start a GENSEC subcontext, with a copy of the properties of the parent
 542  * @param mem_ctx The parent TALLOC memory context.
 543  * @param parent The parent GENSEC context 
 544  * @param gensec_security Returned GENSEC context pointer.
 545  * @note Used by SPNEGO in particular, for the actual implementation mechanism
 546  */
 547 
 548 _PUBLIC_ NTSTATUS gensec_subcontext_start(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 549                                  struct gensec_security *parent, 
 550                                  struct gensec_security **gensec_security)
 551 {
 552         (*gensec_security) = talloc(mem_ctx, struct gensec_security);
 553         NT_STATUS_HAVE_NO_MEMORY(*gensec_security);
 554 
 555         (**gensec_security) = *parent;
 556         (*gensec_security)->ops = NULL;
 557         (*gensec_security)->private_data = NULL;
 558 
 559         (*gensec_security)->subcontext = true;
 560         (*gensec_security)->want_features = parent->want_features;
 561         (*gensec_security)->event_ctx = parent->event_ctx;
 562         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
 563         (*gensec_security)->settings = talloc_reference(*gensec_security, parent->settings);
 564         (*gensec_security)->auth_context = talloc_reference(*gensec_security, parent->auth_context);
 565 
 566         return NT_STATUS_OK;
 567 }
 568 
 569 /**
 570   Start the GENSEC system, in client mode, returning a context pointer.
 571   @param mem_ctx The parent TALLOC memory context.
 572   @param gensec_security Returned GENSEC context pointer.
 573   @note  The mem_ctx is only a parent and may be NULL.
 574 */
 575 _PUBLIC_ NTSTATUS gensec_client_start(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 576                              struct gensec_security **gensec_security,
 577                              struct tevent_context *ev,
 578                              struct gensec_settings *settings)
 579 {
 580         NTSTATUS status;
 581 
 582         if (settings == NULL) {
 583                 DEBUG(0,("gensec_client_start: no settings given!\n"));
 584                 return NT_STATUS_INTERNAL_ERROR;
 585         }
 586 
 587         status = gensec_start(mem_ctx, ev, settings, NULL, gensec_security);
 588         if (!NT_STATUS_IS_OK(status)) {
 589                 return status;
 590         }
 591         (*gensec_security)->gensec_role = GENSEC_CLIENT;
 592 
 593         return status;
 594 }
 595 
 596 /**
 597   Start the GENSEC system, in server mode, returning a context pointer.
 598   @param mem_ctx The parent TALLOC memory context.
 599   @param gensec_security Returned GENSEC context pointer.
 600   @note  The mem_ctx is only a parent and may be NULL.
 601 */
 602 _PUBLIC_ NTSTATUS gensec_server_start(TALLOC_CTX *mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 603                                       struct tevent_context *ev,
 604                                       struct gensec_settings *settings,
 605                                       struct auth_context *auth_context,
 606                                       struct gensec_security **gensec_security)
 607 {
 608         NTSTATUS status;
 609 
 610         if (!ev) {
 611                 DEBUG(0,("gensec_server_start: no event context given!\n"));
 612                 return NT_STATUS_INTERNAL_ERROR;
 613         }
 614 
 615         if (!settings) {
 616                 DEBUG(0,("gensec_server_start: no settings given!\n"));
 617                 return NT_STATUS_INTERNAL_ERROR;
 618         }
 619 
 620         status = gensec_start(mem_ctx, ev, settings, auth_context, gensec_security);
 621         if (!NT_STATUS_IS_OK(status)) {
 622                 return status;
 623         }
 624         (*gensec_security)->gensec_role = GENSEC_SERVER;
 625 
 626         return status;
 627 }
 628 
 629 static NTSTATUS gensec_start_mech(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
 630 {
 631         NTSTATUS status;
 632         DEBUG(5, ("Starting GENSEC %smechanism %s\n", 
 633                   gensec_security->subcontext ? "sub" : "", 
 634                   gensec_security->ops->name));
 635         switch (gensec_security->gensec_role) {
 636         case GENSEC_CLIENT:
 637                 if (gensec_security->ops->client_start) {
 638                         status = gensec_security->ops->client_start(gensec_security);
 639                         if (!NT_STATUS_IS_OK(status)) {
 640                                 DEBUG(2, ("Failed to start GENSEC client mech %s: %s\n",
 641                                           gensec_security->ops->name, nt_errstr(status))); 
 642                         }
 643                         return status;
 644                 }
 645                 break;
 646         case GENSEC_SERVER:
 647                 if (gensec_security->ops->server_start) {
 648                         status = gensec_security->ops->server_start(gensec_security);
 649                         if (!NT_STATUS_IS_OK(status)) {
 650                                 DEBUG(1, ("Failed to start GENSEC server mech %s: %s\n",
 651                                           gensec_security->ops->name, nt_errstr(status))); 
 652                         }
 653                         return status;
 654                 }
 655                 break;
 656         }
 657         return NT_STATUS_INVALID_PARAMETER;
 658 }
 659 
 660 /** 
 661  * Start a GENSEC sub-mechanism by DCERPC allocated 'auth type' number 
 662  * @param gensec_security GENSEC context pointer.
 663  * @param auth_type DCERPC auth type
 664  * @param auth_level DCERPC auth level 
 665  */
 666 
 667 _PUBLIC_ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 668                                        uint8_t auth_type, uint8_t auth_level) 
 669 {
 670         gensec_security->ops = gensec_security_by_authtype(gensec_security, auth_type);
 671         if (!gensec_security->ops) {
 672                 DEBUG(3, ("Could not find GENSEC backend for auth_type=%d\n", (int)auth_type));
 673                 return NT_STATUS_INVALID_PARAMETER;
 674         }
 675         gensec_want_feature(gensec_security, GENSEC_FEATURE_DCE_STYLE);
 676         gensec_want_feature(gensec_security, GENSEC_FEATURE_ASYNC_REPLIES);
 677         if (auth_level == DCERPC_AUTH_LEVEL_INTEGRITY) {
 678                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
 679         } else if (auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
 680                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SIGN);
 681                 gensec_want_feature(gensec_security, GENSEC_FEATURE_SEAL);
 682         } else if (auth_level == DCERPC_AUTH_LEVEL_CONNECT) {
 683                 /* Default features */
 684         } else {
 685                 DEBUG(2,("auth_level %d not supported in DCE/RPC authentication\n", 
 686                          auth_level));
 687                 return NT_STATUS_INVALID_PARAMETER;
 688         }
 689 
 690         return gensec_start_mech(gensec_security);
 691 }
 692 
 693 _PUBLIC_ const char *gensec_get_name_by_authtype(struct gensec_security *gensec_security, uint8_t authtype) 
     /* [<][>][^][v][top][bottom][index][help] */
 694 {
 695         const struct gensec_security_ops *ops;
 696         ops = gensec_security_by_authtype(gensec_security, authtype);
 697         if (ops) {
 698                 return ops->name;
 699         }
 700         return NULL;
 701 }
 702         
 703 
 704 _PUBLIC_ const char *gensec_get_name_by_oid(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
 705                                                                                         const char *oid_string) 
 706 {
 707         const struct gensec_security_ops *ops;
 708         ops = gensec_security_by_oid(gensec_security, oid_string);
 709         if (ops) {
 710                 return ops->name;
 711         }
 712         return oid_string;
 713 }
 714         
 715 
 716 /** 
 717  * Start a GENSEC sub-mechanism with a specifed mechansim structure, used in SPNEGO
 718  *
 719  */
 720 
 721 NTSTATUS gensec_start_mech_by_ops(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 722                                   const struct gensec_security_ops *ops) 
 723 {
 724         gensec_security->ops = ops;
 725         return gensec_start_mech(gensec_security);
 726 }
 727 
 728 /** 
 729  * Start a GENSEC sub-mechanism by OID, used in SPNEGO
 730  *
 731  * @note This should also be used when you wish to just start NLTMSSP (for example), as it uses a
 732  *       well-known #define to hook it in.
 733  */
 734 
 735 _PUBLIC_ NTSTATUS gensec_start_mech_by_oid(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 736                                   const char *mech_oid) 
 737 {
 738         SMB_ASSERT(gensec_security != NULL);
 739 
 740         gensec_security->ops = gensec_security_by_oid(gensec_security, mech_oid);
 741         if (!gensec_security->ops) {
 742                 DEBUG(3, ("Could not find GENSEC backend for oid=%s\n", mech_oid));
 743                 return NT_STATUS_INVALID_PARAMETER;
 744         }
 745         return gensec_start_mech(gensec_security);
 746 }
 747 
 748 /** 
 749  * Start a GENSEC sub-mechanism by a well know SASL name
 750  *
 751  */
 752 
 753 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 754                                         const char *sasl_name) 
 755 {
 756         gensec_security->ops = gensec_security_by_sasl_name(gensec_security, sasl_name);
 757         if (!gensec_security->ops) {
 758                 DEBUG(3, ("Could not find GENSEC backend for sasl_name=%s\n", sasl_name));
 759                 return NT_STATUS_INVALID_PARAMETER;
 760         }
 761         return gensec_start_mech(gensec_security);
 762 }
 763 
 764 /** 
 765  * Start a GENSEC sub-mechanism with the preferred option from a SASL name list
 766  *
 767  */
 768 
 769 _PUBLIC_ NTSTATUS gensec_start_mech_by_sasl_list(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 770                                                  const char **sasl_names) 
 771 {
 772         NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
 773         TALLOC_CTX *mem_ctx = talloc_new(gensec_security);
 774         const struct gensec_security_ops **ops;
 775         int i;
 776         if (!mem_ctx) {
 777                 return NT_STATUS_NO_MEMORY;
 778         }
 779         ops = gensec_security_by_sasl_list(gensec_security, mem_ctx, sasl_names);
 780         if (!ops || !*ops) {
 781                 DEBUG(3, ("Could not find GENSEC backend for any of sasl_name = %s\n", 
 782                           str_list_join(mem_ctx, 
 783                                         sasl_names, ' ')));
 784                 talloc_free(mem_ctx);
 785                 return NT_STATUS_INVALID_PARAMETER;
 786         }
 787         for (i=0; ops[i]; i++) {
 788                 nt_status = gensec_start_mech_by_ops(gensec_security, ops[i]);
 789                 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_INVALID_PARAMETER)) {
 790                         break;
 791                 }
 792         }
 793         talloc_free(mem_ctx);
 794         return nt_status;
 795 }
 796 
 797 /** 
 798  * Start a GENSEC sub-mechanism by an internal name
 799  *
 800  */
 801 
 802 _PUBLIC_ NTSTATUS gensec_start_mech_by_name(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 803                                         const char *name) 
 804 {
 805         gensec_security->ops = gensec_security_by_name(gensec_security, name);
 806         if (!gensec_security->ops) {
 807                 DEBUG(3, ("Could not find GENSEC backend for name=%s\n", name));
 808                 return NT_STATUS_INVALID_PARAMETER;
 809         }
 810         return gensec_start_mech(gensec_security);
 811 }
 812 
 813 /*
 814   wrappers for the gensec function pointers
 815 */
 816 _PUBLIC_ NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 817                               TALLOC_CTX *mem_ctx, 
 818                               uint8_t *data, size_t length, 
 819                               const uint8_t *whole_pdu, size_t pdu_length, 
 820                               const DATA_BLOB *sig)
 821 {
 822         if (!gensec_security->ops->unseal_packet) {
 823                 return NT_STATUS_NOT_IMPLEMENTED;
 824         }
 825         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 826                 return NT_STATUS_INVALID_PARAMETER;
 827         }
 828         
 829         return gensec_security->ops->unseal_packet(gensec_security, mem_ctx, 
 830                                                    data, length, 
 831                                                    whole_pdu, pdu_length, 
 832                                                    sig);
 833 }
 834 
 835 _PUBLIC_ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 836                              TALLOC_CTX *mem_ctx, 
 837                              const uint8_t *data, size_t length, 
 838                              const uint8_t *whole_pdu, size_t pdu_length, 
 839                              const DATA_BLOB *sig)
 840 {
 841         if (!gensec_security->ops->check_packet) {
 842                 return NT_STATUS_NOT_IMPLEMENTED;
 843         }
 844         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 845                 return NT_STATUS_INVALID_PARAMETER;
 846         }
 847         
 848         return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 849 }
 850 
 851 _PUBLIC_ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 852                             TALLOC_CTX *mem_ctx, 
 853                             uint8_t *data, size_t length, 
 854                             const uint8_t *whole_pdu, size_t pdu_length, 
 855                             DATA_BLOB *sig)
 856 {
 857         if (!gensec_security->ops->seal_packet) {
 858                 return NT_STATUS_NOT_IMPLEMENTED;
 859         }
 860         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL)) {
 861                 return NT_STATUS_INVALID_PARAMETER;
 862         }
 863         
 864         return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 865 }
 866 
 867 _PUBLIC_ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 868                             TALLOC_CTX *mem_ctx, 
 869                             const uint8_t *data, size_t length, 
 870                             const uint8_t *whole_pdu, size_t pdu_length, 
 871                             DATA_BLOB *sig)
 872 {
 873         if (!gensec_security->ops->sign_packet) {
 874                 return NT_STATUS_NOT_IMPLEMENTED;
 875         }
 876         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 877                 return NT_STATUS_INVALID_PARAMETER;
 878         }
 879         
 880         return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 881 }
 882 
 883 _PUBLIC_ size_t gensec_sig_size(struct gensec_security *gensec_security, size_t data_size) 
     /* [<][>][^][v][top][bottom][index][help] */
 884 {
 885         if (!gensec_security->ops->sig_size) {
 886                 return 0;
 887         }
 888         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SIGN)) {
 889                 return 0;
 890         }
 891         
 892         return gensec_security->ops->sig_size(gensec_security, data_size);
 893 }
 894 
 895 size_t gensec_max_wrapped_size(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
 896 {
 897         if (!gensec_security->ops->max_wrapped_size) {
 898                 return (1 << 17);
 899         }
 900         
 901         return gensec_security->ops->max_wrapped_size(gensec_security);
 902 }
 903 
 904 size_t gensec_max_input_size(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
 905 {
 906         if (!gensec_security->ops->max_input_size) {
 907                 return (1 << 17) - gensec_sig_size(gensec_security, 1 << 17);
 908         }
 909         
 910         return gensec_security->ops->max_input_size(gensec_security);
 911 }
 912 
 913 _PUBLIC_ NTSTATUS gensec_wrap(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 914                      TALLOC_CTX *mem_ctx, 
 915                      const DATA_BLOB *in, 
 916                      DATA_BLOB *out) 
 917 {
 918         if (!gensec_security->ops->wrap) {
 919                 return NT_STATUS_NOT_IMPLEMENTED;
 920         }
 921         return gensec_security->ops->wrap(gensec_security, mem_ctx, in, out);
 922 }
 923 
 924 _PUBLIC_ NTSTATUS gensec_unwrap(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 925                        TALLOC_CTX *mem_ctx, 
 926                        const DATA_BLOB *in, 
 927                        DATA_BLOB *out) 
 928 {
 929         if (!gensec_security->ops->unwrap) {
 930                 return NT_STATUS_NOT_IMPLEMENTED;
 931         }
 932         return gensec_security->ops->unwrap(gensec_security, mem_ctx, in, out);
 933 }
 934 
 935 _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 936                             DATA_BLOB *session_key)
 937 {
 938         if (!gensec_security->ops->session_key) {
 939                 return NT_STATUS_NOT_IMPLEMENTED;
 940         }
 941         if (!gensec_have_feature(gensec_security, GENSEC_FEATURE_SESSION_KEY)) {
 942                 return NT_STATUS_NO_USER_SESSION_KEY;
 943         }
 944         
 945         return gensec_security->ops->session_key(gensec_security, session_key);
 946 }
 947 
 948 /** 
 949  * Return the credentials of a logged on user, including session keys
 950  * etc.
 951  *
 952  * Only valid after a successful authentication
 953  *
 954  * May only be called once per authentication.
 955  *
 956  */
 957 
 958 _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security, 
     /* [<][>][^][v][top][bottom][index][help] */
 959                              struct auth_session_info **session_info)
 960 {
 961         if (!gensec_security->ops->session_info) {
 962                 return NT_STATUS_NOT_IMPLEMENTED;
 963         }
 964         return gensec_security->ops->session_info(gensec_security, session_info);
 965 }
 966 
 967 /**
 968  * Next state function for the GENSEC state machine
 969  * 
 970  * @param gensec_security GENSEC State
 971  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
 972  * @param in The request, as a DATA_BLOB
 973  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
 974  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
 975  *                or NT_STATUS_OK if the user is authenticated. 
 976  */
 977 
 978 _PUBLIC_ NTSTATUS gensec_update(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx, 
     /* [<][>][^][v][top][bottom][index][help] */
 979                        const DATA_BLOB in, DATA_BLOB *out) 
 980 {
 981         return gensec_security->ops->update(gensec_security, out_mem_ctx, in, out);
 982 }
 983 
 984 static void gensec_update_async_timed_handler(struct tevent_context *ev, struct tevent_timer *te,
     /* [<][>][^][v][top][bottom][index][help] */
 985                                               struct timeval t, void *ptr)
 986 {
 987         struct gensec_update_request *req = talloc_get_type(ptr, struct gensec_update_request);
 988         req->status = req->gensec_security->ops->update(req->gensec_security, req, req->in, &req->out);
 989         req->callback.fn(req, req->callback.private_data);
 990 }
 991 
 992 /**
 993  * Next state function for the GENSEC state machine async version
 994  * 
 995  * @param gensec_security GENSEC State
 996  * @param in The request, as a DATA_BLOB
 997  * @param callback The function that will be called when the operation is
 998  *                 finished, it should return gensec_update_recv() to get output
 999  * @param private_data A private pointer that will be passed to the callback function
1000  */
1001 
1002 _PUBLIC_ void gensec_update_send(struct gensec_security *gensec_security, const DATA_BLOB in,
     /* [<][>][^][v][top][bottom][index][help] */
1003                                  void (*callback)(struct gensec_update_request *req, void *private_data),
1004                                  void *private_data)
1005 {
1006         struct gensec_update_request *req = NULL;
1007         struct tevent_timer *te = NULL;
1008 
1009         req = talloc(gensec_security, struct gensec_update_request);
1010         if (!req) goto failed;
1011         req->gensec_security            = gensec_security;
1012         req->in                         = in;
1013         req->out                        = data_blob(NULL, 0);
1014         req->callback.fn                = callback;
1015         req->callback.private_data      = private_data;
1016 
1017         te = event_add_timed(gensec_security->event_ctx, req,
1018                              timeval_zero(),
1019                              gensec_update_async_timed_handler, req);
1020         if (!te) goto failed;
1021 
1022         return;
1023 
1024 failed:
1025         talloc_free(req);
1026         callback(NULL, private_data);
1027 }
1028 
1029 /**
1030  * Next state function for the GENSEC state machine
1031  * 
1032  * @param req GENSEC update request state
1033  * @param out_mem_ctx The TALLOC_CTX for *out to be allocated on
1034  * @param out The reply, as an talloc()ed DATA_BLOB, on *out_mem_ctx
1035  * @return Error, MORE_PROCESSING_REQUIRED if a reply is sent, 
1036  *                or NT_STATUS_OK if the user is authenticated. 
1037  */
1038 _PUBLIC_ NTSTATUS gensec_update_recv(struct gensec_update_request *req, TALLOC_CTX *out_mem_ctx, DATA_BLOB *out)
     /* [<][>][^][v][top][bottom][index][help] */
1039 {
1040         NTSTATUS status;
1041 
1042         NT_STATUS_HAVE_NO_MEMORY(req);
1043 
1044         *out = req->out;
1045         talloc_steal(out_mem_ctx, out->data);
1046         status = req->status;
1047 
1048         talloc_free(req);
1049         return status;
1050 }
1051 
1052 /** 
1053  * Set the requirement for a certain feature on the connection
1054  *
1055  */
1056 
1057 _PUBLIC_ void gensec_want_feature(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
1058                          uint32_t feature) 
1059 {
1060         if (!gensec_security->ops || !gensec_security->ops->want_feature) {
1061                 gensec_security->want_features |= feature;
1062                 return;
1063         }
1064         gensec_security->ops->want_feature(gensec_security, feature);
1065 }
1066 
1067 /** 
1068  * Check the requirement for a certain feature on the connection
1069  *
1070  */
1071 
1072 _PUBLIC_ bool gensec_have_feature(struct gensec_security *gensec_security,
     /* [<][>][^][v][top][bottom][index][help] */
1073                          uint32_t feature) 
1074 {
1075         if (!gensec_security->ops->have_feature) {
1076                 return false;
1077         }
1078         
1079         /* We might 'have' features that we don't 'want', because the
1080          * other end demanded them, or we can't neotiate them off */
1081         return gensec_security->ops->have_feature(gensec_security, feature);
1082 }
1083 
1084 /** 
1085  * Associate a credentials structure with a GENSEC context - talloc_reference()s it to the context 
1086  *
1087  */
1088 
1089 _PUBLIC_ NTSTATUS gensec_set_credentials(struct gensec_security *gensec_security, struct cli_credentials *credentials) 
     /* [<][>][^][v][top][bottom][index][help] */
1090 {
1091         gensec_security->credentials = talloc_reference(gensec_security, credentials);
1092         NT_STATUS_HAVE_NO_MEMORY(gensec_security->credentials);
1093         gensec_want_feature(gensec_security, cli_credentials_get_gensec_features(gensec_security->credentials));
1094         return NT_STATUS_OK;
1095 }
1096 
1097 /** 
1098  * Return the credentials structure associated with a GENSEC context
1099  *
1100  */
1101 
1102 _PUBLIC_ struct cli_credentials *gensec_get_credentials(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
1103 {
1104         if (!gensec_security) {
1105                 return NULL;
1106         }
1107         return gensec_security->credentials;
1108 }
1109 
1110 /** 
1111  * Set the target service (such as 'http' or 'host') on a GENSEC context - ensures it is talloc()ed 
1112  *
1113  */
1114 
1115 _PUBLIC_ NTSTATUS gensec_set_target_service(struct gensec_security *gensec_security, const char *service) 
     /* [<][>][^][v][top][bottom][index][help] */
1116 {
1117         gensec_security->target.service = talloc_strdup(gensec_security, service);
1118         if (!gensec_security->target.service) {
1119                 return NT_STATUS_NO_MEMORY;
1120         }
1121         return NT_STATUS_OK;
1122 }
1123 
1124 _PUBLIC_ const char *gensec_get_target_service(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
1125 {
1126         if (gensec_security->target.service) {
1127                 return gensec_security->target.service;
1128         }
1129 
1130         return "host";
1131 }
1132 
1133 /** 
1134  * Set the target hostname (suitable for kerberos resolutation) on a GENSEC context - ensures it is talloc()ed 
1135  *
1136  */
1137 
1138 _PUBLIC_ NTSTATUS gensec_set_target_hostname(struct gensec_security *gensec_security, const char *hostname) 
     /* [<][>][^][v][top][bottom][index][help] */
1139 {
1140         gensec_security->target.hostname = talloc_strdup(gensec_security, hostname);
1141         if (hostname && !gensec_security->target.hostname) {
1142                 return NT_STATUS_NO_MEMORY;
1143         }
1144         return NT_STATUS_OK;
1145 }
1146 
1147 _PUBLIC_ const char *gensec_get_target_hostname(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
1148 {
1149         /* We allow the target hostname to be overriden for testing purposes */
1150         if (gensec_security->settings->target_hostname) {
1151                 return gensec_security->settings->target_hostname;
1152         }
1153 
1154         if (gensec_security->target.hostname) {
1155                 return gensec_security->target.hostname;
1156         }
1157 
1158         /* We could add use the 'set sockaddr' call, and do a reverse
1159          * lookup, but this would be both insecure (compromising the
1160          * way kerberos works) and add DNS timeouts */
1161         return NULL;
1162 }
1163 
1164 /** 
1165  * Set (and talloc_reference) local and peer socket addresses onto a socket context on the GENSEC context 
1166  *
1167  * This is so that kerberos can include these addresses in
1168  * cryptographic tokens, to avoid certain attacks.
1169  */
1170 
1171 _PUBLIC_ NTSTATUS gensec_set_my_addr(struct gensec_security *gensec_security, struct socket_address *my_addr) 
     /* [<][>][^][v][top][bottom][index][help] */
1172 {
1173         gensec_security->my_addr = my_addr;
1174         if (my_addr && !talloc_reference(gensec_security, my_addr)) {
1175                 return NT_STATUS_NO_MEMORY;
1176         }
1177         return NT_STATUS_OK;
1178 }
1179 
1180 _PUBLIC_ NTSTATUS gensec_set_peer_addr(struct gensec_security *gensec_security, struct socket_address *peer_addr) 
     /* [<][>][^][v][top][bottom][index][help] */
1181 {
1182         gensec_security->peer_addr = peer_addr;
1183         if (peer_addr && !talloc_reference(gensec_security, peer_addr)) {
1184                 return NT_STATUS_NO_MEMORY;
1185         }
1186         return NT_STATUS_OK;
1187 }
1188 
1189 struct socket_address *gensec_get_my_addr(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
1190 {
1191         if (gensec_security->my_addr) {
1192                 return gensec_security->my_addr;
1193         }
1194 
1195         /* We could add a 'set sockaddr' call, and do a lookup.  This
1196          * would avoid needing to do system calls if nothing asks. */
1197         return NULL;
1198 }
1199 
1200 _PUBLIC_ struct socket_address *gensec_get_peer_addr(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
1201 {
1202         if (gensec_security->peer_addr) {
1203                 return gensec_security->peer_addr;
1204         }
1205 
1206         /* We could add a 'set sockaddr' call, and do a lookup.  This
1207          * would avoid needing to do system calls if nothing asks.
1208          * However, this is not appropriate for the peer addres on
1209          * datagram sockets */
1210         return NULL;
1211 }
1212 
1213 
1214 
1215 /** 
1216  * Set the target principal (assuming it it known, say from the SPNEGO reply)
1217  *  - ensures it is talloc()ed 
1218  *
1219  */
1220 
1221 NTSTATUS gensec_set_target_principal(struct gensec_security *gensec_security, const char *principal) 
     /* [<][>][^][v][top][bottom][index][help] */
1222 {
1223         gensec_security->target.principal = talloc_strdup(gensec_security, principal);
1224         if (!gensec_security->target.principal) {
1225                 return NT_STATUS_NO_MEMORY;
1226         }
1227         return NT_STATUS_OK;
1228 }
1229 
1230 const char *gensec_get_target_principal(struct gensec_security *gensec_security) 
     /* [<][>][^][v][top][bottom][index][help] */
1231 {
1232         if (gensec_security->target.principal) {
1233                 return gensec_security->target.principal;
1234         }
1235 
1236         return NULL;
1237 }
1238 
1239 /*
1240   register a GENSEC backend. 
1241 
1242   The 'name' can be later used by other backends to find the operations
1243   structure for this backend.
1244 */
1245 NTSTATUS gensec_register(const struct gensec_security_ops *ops)
     /* [<][>][^][v][top][bottom][index][help] */
1246 {
1247         if (gensec_security_by_name(NULL, ops->name) != NULL) {
1248                 /* its already registered! */
1249                 DEBUG(0,("GENSEC backend '%s' already registered\n", 
1250                          ops->name));
1251                 return NT_STATUS_OBJECT_NAME_COLLISION;
1252         }
1253 
1254         generic_security_ops = talloc_realloc(talloc_autofree_context(), 
1255                                               generic_security_ops, 
1256                                               struct gensec_security_ops *, 
1257                                               gensec_num_backends+2);
1258         if (!generic_security_ops) {
1259                 return NT_STATUS_NO_MEMORY;
1260         }
1261 
1262         generic_security_ops[gensec_num_backends] = discard_const_p(struct gensec_security_ops, ops);
1263         gensec_num_backends++;
1264         generic_security_ops[gensec_num_backends] = NULL;
1265 
1266         DEBUG(3,("GENSEC backend '%s' registered\n", 
1267                  ops->name));
1268 
1269         return NT_STATUS_OK;
1270 }
1271 
1272 /*
1273   return the GENSEC interface version, and the size of some critical types
1274   This can be used by backends to either detect compilation errors, or provide
1275   multiple implementations for different smbd compilation options in one module
1276 */
1277 const struct gensec_critical_sizes *gensec_interface_version(void)
     /* [<][>][^][v][top][bottom][index][help] */
1278 {
1279         static const struct gensec_critical_sizes critical_sizes = {
1280                 GENSEC_INTERFACE_VERSION,
1281                 sizeof(struct gensec_security_ops),
1282                 sizeof(struct gensec_security),
1283         };
1284 
1285         return &critical_sizes;
1286 }
1287 
1288 static int sort_gensec(struct gensec_security_ops **gs1, struct gensec_security_ops **gs2) {
     /* [<][>][^][v][top][bottom][index][help] */
1289         return (*gs2)->priority - (*gs1)->priority;
1290 }
1291 
1292 int gensec_setting_int(struct gensec_settings *settings, const char *mechanism, const char *name, int default_value)
     /* [<][>][^][v][top][bottom][index][help] */
1293 {
1294         return lp_parm_int(settings->lp_ctx, NULL, mechanism, name, default_value);
1295 }
1296 
1297 bool gensec_setting_bool(struct gensec_settings *settings, const char *mechanism, const char *name, bool default_value)
     /* [<][>][^][v][top][bottom][index][help] */
1298 {
1299         return lp_parm_bool(settings->lp_ctx, NULL, mechanism, name, default_value);
1300 }
1301 
1302 /*
1303   initialise the GENSEC subsystem
1304 */
1305 _PUBLIC_ NTSTATUS gensec_init(struct loadparm_context *lp_ctx)
     /* [<][>][^][v][top][bottom][index][help] */
1306 {
1307         static bool initialized = false;
1308         extern NTSTATUS gensec_sasl_init(void);
1309         extern NTSTATUS gensec_krb5_init(void);
1310         extern NTSTATUS gensec_schannel_init(void);
1311         extern NTSTATUS gensec_spnego_init(void);
1312         extern NTSTATUS gensec_gssapi_init(void);
1313         extern NTSTATUS gensec_ntlmssp_init(void);
1314 
1315         init_module_fn static_init[] = { STATIC_gensec_MODULES };
1316         init_module_fn *shared_init;
1317 
1318         if (initialized) return NT_STATUS_OK;
1319         initialized = true;
1320         
1321         shared_init = load_samba_modules(NULL, lp_ctx, "gensec");
1322 
1323         run_init_functions(static_init);
1324         run_init_functions(shared_init);
1325 
1326         talloc_free(shared_init);
1327 
1328         qsort(generic_security_ops, gensec_num_backends, sizeof(*generic_security_ops), QSORT_CAST sort_gensec);
1329         
1330         return NT_STATUS_OK;
1331 }

/* [<][>][^][v][top][bottom][index][help] */