libads/smb_krb5_locator.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    kerberos locator plugin
00004    Copyright (C) Guenther Deschner 2007
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #include "includes.h"
00022 
00023 #if defined(HAVE_KRB5) && defined(HAVE_KRB5_LOCATE_PLUGIN_H)
00024 
00025 #include <krb5/locate_plugin.h>
00026 
00027 static const char *get_service_from_locate_service_type(enum locate_service_type svc)
00028 {
00029         switch (svc) {
00030                 case locate_service_kdc:
00031                 case locate_service_master_kdc:
00032                         return "88";
00033                 case locate_service_kadmin:
00034                 case locate_service_krb524:
00035                         /* not supported */
00036                         return NULL;
00037                 case locate_service_kpasswd:
00038                         return "464";
00039                 default:
00040                         break;
00041         }
00042         return NULL;
00043 
00044 }
00045 
00046 static const char *locate_service_type_name(enum locate_service_type svc)
00047 {
00048         switch (svc) {
00049                 case locate_service_kdc:
00050                         return "locate_service_kdc";
00051                 case locate_service_master_kdc:
00052                         return "locate_service_master_kdc";
00053                 case locate_service_kadmin:
00054                         return "locate_service_kadmin";
00055                 case locate_service_krb524:
00056                         return "locate_service_krb524";
00057                 case locate_service_kpasswd:
00058                         return "locate_service_kpasswd";
00059                 default:
00060                         break;
00061         }
00062         return NULL;
00063 }
00064 
00065 static const char *socktype_name(int socktype)
00066 {
00067         switch (socktype) {
00068                 case SOCK_STREAM:
00069                         return "SOCK_STREAM";
00070                 case SOCK_DGRAM:
00071                         return "SOCK_DGRAM";
00072                 default:
00073                         break;
00074         }
00075         return "unknown";
00076 }
00077 
00078 static const char *family_name(int family)
00079 {
00080         switch (family) {
00081                 case AF_UNSPEC:
00082                         return "AF_UNSPEC";
00083                 case AF_INET:
00084                         return "AF_INET";
00085                 case AF_INET6:
00086                         return "AF_INET6";
00087                 default:
00088                         break;
00089         }
00090         return "unknown";
00091 }
00092 
00093 /**
00094  * Check input parameters, return KRB5_PLUGIN_NO_HANDLE for unsupported ones
00095  *
00096  * @param svc 
00097  * @param realm string
00098  * @param socktype integer
00099  * @param family integer
00100  *
00101  * @return integer.
00102  */
00103 
00104 static int smb_krb5_locator_lookup_sanity_check(enum locate_service_type svc,
00105                                                 const char *realm,
00106                                                 int socktype,
00107                                                 int family)
00108 {
00109         if (!realm || strlen(realm) == 0) {
00110                 return EINVAL;
00111         }
00112 
00113         switch (svc) {
00114                 case locate_service_kdc:
00115                 case locate_service_master_kdc:
00116                 case locate_service_kpasswd:
00117                         break;
00118                 case locate_service_kadmin:
00119                 case locate_service_krb524:
00120 #ifdef KRB5_PLUGIN_NO_HANDLE
00121                         return KRB5_PLUGIN_NO_HANDLE;
00122 #else
00123                         return KRB5_KDC_UNREACH; /* Heimdal */
00124 #endif
00125                 default:
00126                         return EINVAL;
00127         }
00128 
00129         switch (family) {
00130                 case AF_UNSPEC:
00131                 case AF_INET:
00132                         break;
00133                 case AF_INET6: /* not yet */
00134 #ifdef KRB5_PLUGIN_NO_HANDLE
00135                         return KRB5_PLUGIN_NO_HANDLE;
00136 #else
00137                         return KRB5_KDC_UNREACH; /* Heimdal */
00138 #endif
00139                 default:
00140                         return EINVAL;
00141         }
00142 
00143         switch (socktype) {
00144                 case SOCK_STREAM:
00145                 case SOCK_DGRAM:
00146                 case 0: /* Heimdal uses that */
00147                         break;
00148                 default:
00149                         return EINVAL;
00150         }
00151 
00152         return 0;
00153 }
00154 
00155 /**
00156  * Try to get addrinfo for a given host and call the krb5 callback
00157  *
00158  * @param name string
00159  * @param service string
00160  * @param in struct addrinfo hint
00161  * @param cbfunc krb5 callback function
00162  * @param cbdata void pointer cbdata
00163  *
00164  * @return krb5_error_code.
00165  */
00166 
00167 static krb5_error_code smb_krb5_locator_call_cbfunc(const char *name, 
00168                                                     const char *service,
00169                                                     struct addrinfo *in,
00170                                                     int (*cbfunc)(void *, int, struct sockaddr *),
00171                                                     void *cbdata)
00172 {
00173         struct addrinfo *out;
00174         int ret;
00175         int count = 3;
00176 
00177         while (count) {
00178 
00179                 ret = getaddrinfo(name, service, in, &out);
00180                 if (ret == 0) {
00181                         break;
00182                 }
00183 
00184                 if (ret == EAI_AGAIN) {
00185                         count--;
00186                         continue;
00187                 }
00188 
00189                 DEBUG(10,("smb_krb5_locator_lookup: got ret: %s (%d)\n", 
00190                         gai_strerror(ret), ret));
00191 #ifdef KRB5_PLUGIN_NO_HANDLE
00192                 return KRB5_PLUGIN_NO_HANDLE;
00193 #else
00194                 return KRB5_KDC_UNREACH; /* Heimdal */
00195 #endif
00196         }
00197 
00198         ret = cbfunc(cbdata, out->ai_socktype, out->ai_addr);
00199         if (ret) {
00200                 DEBUG(10,("smb_krb5_locator_lookup: failed to call callback: %s (%d)\n", 
00201                         error_message(ret), ret));
00202         }
00203 
00204         freeaddrinfo(out);
00205 
00206         return ret;
00207 }
00208 
00209 /**
00210  * PUBLIC INTERFACE: locate init
00211  *
00212  * @param context krb5_context
00213  * @param privata_data pointer to private data pointer
00214  *
00215  * @return krb5_error_code.
00216  */
00217 
00218 krb5_error_code smb_krb5_locator_init(krb5_context context, 
00219                                       void **private_data)
00220 {
00221         setup_logging("smb_krb5_locator", True);
00222         load_case_tables();
00223         lp_load(dyn_CONFIGFILE,True,False,False,True);
00224 
00225         DEBUG(10,("smb_krb5_locator_init: called\n"));
00226 
00227         return 0;
00228 }
00229 
00230 /**
00231  * PUBLIC INTERFACE: close locate
00232  *
00233  * @param private_data pointer to private data
00234  *
00235  * @return void.
00236  */
00237 
00238 void smb_krb5_locator_close(void *private_data)
00239 {
00240         DEBUG(10,("smb_krb5_locator_close: called\n"));
00241 
00242         /* gfree_all(); */
00243 }
00244 
00245 /**
00246  * PUBLIC INTERFACE: locate lookup
00247  *
00248  * @param private_data pointer to private data
00249  * @param svc enum locate_service_type.
00250  * @param realm string
00251  * @param socktype integer
00252  * @param family integer
00253  * @param cbfunc callback function to send back entries
00254  * @param cbdata void pointer to cbdata
00255  *
00256  * @return krb5_error_code.
00257  */
00258 
00259 krb5_error_code smb_krb5_locator_lookup(void *private_data,
00260                                         enum locate_service_type svc,
00261                                         const char *realm,
00262                                         int socktype,
00263                                         int family,
00264                                         int (*cbfunc)(void *, int, struct sockaddr *),
00265                                         void *cbdata)
00266 {
00267         NTSTATUS status;
00268         krb5_error_code ret;
00269         char *sitename = NULL;
00270         struct ip_service *ip_list;
00271         int count = 0;
00272         struct addrinfo aihints;
00273         char *saf_name = NULL;
00274         int i;
00275 
00276         DEBUG(10,("smb_krb5_locator_lookup: called for\n"));
00277         DEBUGADD(10,("\tsvc: %s (%d), realm: %s\n", 
00278                 locate_service_type_name(svc), svc, realm));
00279         DEBUGADD(10,("\tsocktype: %s (%d), family: %s (%d)\n", 
00280                 socktype_name(socktype), socktype,
00281                 family_name(family), family));
00282 
00283         ret = smb_krb5_locator_lookup_sanity_check(svc, realm, socktype, family);
00284         if (ret) {
00285                 DEBUG(10,("smb_krb5_locator_lookup: returning ret: %s (%d)\n", 
00286                         error_message(ret), ret));
00287                 return ret;
00288         }
00289 
00290         /* first try to fetch from SAF cache */
00291 
00292         saf_name = saf_fetch(realm);
00293         if (!saf_name || strlen(saf_name) == 0) {
00294                 DEBUG(10,("smb_krb5_locator_lookup: no SAF name stored for %s\n", 
00295                         realm));
00296                 goto find_kdc;
00297         }
00298 
00299         DEBUG(10,("smb_krb5_locator_lookup: got %s for %s from SAF cache\n", 
00300                 saf_name, realm));
00301 
00302         ZERO_STRUCT(aihints);
00303         
00304         aihints.ai_family = family;
00305         aihints.ai_socktype = socktype;
00306 
00307         ret = smb_krb5_locator_call_cbfunc(saf_name, 
00308                                           get_service_from_locate_service_type(svc), 
00309                                           &aihints, 
00310                                           cbfunc, cbdata);
00311         if (ret) {
00312                 return ret;
00313         }
00314 
00315         return 0;
00316 
00317  find_kdc:
00318 
00319         /* now try to find via site-aware DNS SRV query */
00320 
00321         sitename = sitename_fetch(realm);
00322         status = get_kdc_list(realm, sitename, &ip_list, &count);
00323 
00324         /* if we didn't found any KDCs on our site go to the main list */
00325 
00326         if (NT_STATUS_IS_OK(status) && sitename && (count == 0)) {
00327                 SAFE_FREE(ip_list);
00328                 SAFE_FREE(sitename);
00329                 status = get_kdc_list(realm, NULL, &ip_list, &count);
00330         }
00331 
00332         SAFE_FREE(sitename);
00333 
00334         if (!NT_STATUS_IS_OK(status)) {
00335                 DEBUG(10,("smb_krb5_locator_lookup: got %s (%s)\n",
00336                         nt_errstr(status), 
00337                         error_message(nt_status_to_krb5(status))));
00338 #ifdef KRB5_PLUGIN_NO_HANDLE
00339                 return KRB5_PLUGIN_NO_HANDLE;
00340 #else
00341                 return KRB5_KDC_UNREACH; /* Heimdal */
00342 #endif
00343         }
00344 
00345         for (i=0; i<count; i++) {
00346 
00347                 const char *host = NULL;
00348                 const char *port = NULL;
00349 
00350                 ZERO_STRUCT(aihints);
00351 
00352                 aihints.ai_family = family;
00353                 aihints.ai_socktype = socktype;
00354 
00355                 host = inet_ntoa(ip_list[i].ip);
00356                 port = get_service_from_locate_service_type(svc);
00357 
00358                 ret = smb_krb5_locator_call_cbfunc(host,
00359                                                   port,
00360                                                   &aihints, 
00361                                                   cbfunc, cbdata);
00362                 if (ret) {
00363                         /* got error */
00364                         break;
00365                 }
00366         }
00367 
00368         SAFE_FREE(ip_list);
00369 
00370         return ret;
00371 }
00372 
00373 #ifdef HEIMDAL_KRB5_LOCATE_PLUGIN_H
00374 #define SMB_KRB5_LOCATOR_SYMBOL_NAME resolve /* Heimdal */
00375 #else
00376 #define SMB_KRB5_LOCATOR_SYMBOL_NAME service_locator /* MIT */
00377 #endif
00378 
00379 const krb5plugin_service_locate_ftable SMB_KRB5_LOCATOR_SYMBOL_NAME = {
00380         0, /* version */
00381         smb_krb5_locator_init,
00382         smb_krb5_locator_close,
00383         smb_krb5_locator_lookup,
00384 };
00385 
00386 #endif

Sambaに対してSat Aug 29 21:23:01 2009に生成されました。  doxygen 1.4.7