Opening Samba TO A WIDER WORLD WITH PLUGINS
 

Sumit BOSE - Red HAT

What is a plugin?

PLUGINS provided by SAMBA

Plugins USED BY SAMBA

Examples for identiTy plugins

What is a plugin?

Loaded dynamical at runtime

Provide a fixed set of objects

What is a plugin?

Plugin vs Library

Library

Must be available at runtime

Same Version as at buildtime

API defined by the Library

No alternatives possible¹

Genral Purpose

Plugin

May not be available at runtime

LoadeD conditionally

Multiple versions possibLe

Stackable

Caller defines the API

Application specifc

PluginS SAMBA provides

Plugin defined outside of Samba

PAM

struct pam_module _pam_example_modstruct ={
     "pam_example",
     pam_example_sm_authenticate,
     pam_example_sm_setcred,
     pam_example_sm_acct_mgmt,
     pam_example_sm_open_session,
     pam_example_sm_close_session,
     pam_example_sm_chauthtok
};

pam_example.so

NSS

enum nss_status _nss_example_getpwnam_r(const char *name, struct passwd *result,
                                    char *buffer, size_t buflen, int *errnop);
enum nss_status _nss_example_getpwuid_r(uid_t uid, struct passwd *result,
                                    char *buffer, size_t buflen, int *errnop);
enum nss_status _nss_example_setpwent(void);
enum nss_status _nss_example_getpwent_r(struct passwd *result,
                                    char *buffer, size_t buflen,
                                    int *errnop);
enum nss_status _nss_example_endpwent(void);


enum nss_status _nss_eaxmple_initgroups_dyn(const char *user, gid_t group,
                                        long int *start, long int *size,
                                        gid_t **groups, long int limit,
                                        int *errnop);

enum nss_status _nss_example_getgrnam_r(const char *name, struct group *result,
                                    char *buffer, size_t buflen, int *errnop);
...

libnss_example.so.2

Kerberos Locator Plugin

typedef struct krb5plugin_service_locate_ftable {
    int minor_version;          /* currently 0 */
    /* Per-context setup and teardown.  Returned void* blob is
       private to the plugin.  */
    krb5_error_code (*init)(krb5_context, void **);
    void (*fini)(void *);
    /* Callback function returns non-zero if the plugin function
       should quit and return; this may be because of an error, or may
       indicate we've already contacted the service, whatever.  The
       lookup function should only return an error if it detects a
       problem, not if the callback function tells it to quit.  */
    krb5_error_code (*lookup)(void *,
                              enum locate_service_type svc, const char *realm,
                              int socktype, int family,
                              int (*cbfunc)(void *,int,struct sockaddr *),
                              void *cbdata);
} krb5plugin_service_locate_ftable;

MIT KErberos version

BIND DLZ PlugiN

typedef int dlz_dlopen_version_t (unsigned int *flags);
typedef isc_result_t dlz_dlopen_create_t (const char *dlzname,
                                          unsigned int argc,
                                          char *argv[],
                                          void **dbdata,
                                          ...);
typedef void dlz_dlopen_destroy_t (void *dbdata);
typedef isc_result_t dlz_dlopen_findzonedb_t (void *dbdata,
                                              const char *name);
typedef isc_result_t dlz_dlopen_lookup_t (const char *zone,
                                          const char *name,
                                          void *dbdata,
                                          dns_sdlzlookup_t *lookup,
                                          dns_clientinfomethods_t *methods,
                                          dns_clientinfo_t *clientinfo);

... 16 calls in the minimal set ...

BIND DLZ PlugiN

Dynamic database API aka DynDB for BIND 9

https://fedorahosted.org/bind-dyndb-ldap/wiki/BIND9/Patches

WIP

Hopefully available with bind 9.11

DNSSEC

incremental zone transfers

transactions

KDB BACKEND

MIT Kerberos Version

typedef struct _kdb_vftabl {
    short int maj_ver;
    short int min_ver;
    krb5_error_code (*init_library)(void);
    krb5_error_code (*fini_library)(void);
    krb5_error_code (*init_module)(krb5_context kcontext, char *conf_section,
                                   char **db_args, int mode);
    krb5_error_code (*fini_module)(krb5_context kcontext);
    krb5_error_code (*create)(krb5_context kcontext, char *conf_section,
                              char **db_args);
    krb5_error_code (*destroy)(krb5_context kcontext, char *conf_section,
                               char **db_args);
    krb5_error_code (*get_age)(krb5_context kcontext, char *db_name,
                               time_t *age);
    krb5_error_code (*lock)(krb5_context kcontext, int mode);
    krb5_error_code (*unlock)(krb5_context kcontext);
    krb5_error_code (*get_principal)(krb5_context kcontext,
                                     krb5_const_principal search_for,
                                     unsigned int flags,
                                     krb5_db_entry **entry);

... about 40 calls in total ...

KDB BACKEND

MIT Kerberos Version

PluginS useD BY Samba

Plugin defined inside of Samba

Registration call

NTSTATUS smb_register_plugin_type(
                 int version,
                 const char *name,
                (plugin_type_init_function init|
                 struct plugin_type_methods *methods));

Auth plugin

typedef struct auth_methods
{
        struct auth_methods *prev, *next;
        const char *name; /* What name got this module */

        NTSTATUS (*auth)(const struct auth_context *auth_context,
                         void *my_private_data,
                         TALLOC_CTX *mem_ctx,
                         const struct auth_usersupplied_info *user_info,
                         struct auth_serversupplied_info **server_info);

        /* Optional methods allowing this module to provide a way to get a gensec context and an auth4_context */
        prepare_gensec_fn prepare_gensec;
        make_auth4_context_fn make_auth4_context;
        /* Used to keep tabs on things like the cli for SMB server authentication */
        void *private_data;

        uint32_t flags;

} auth_methods;

auth methods or security in smb.conf

PerfcounT module

Perfcount Module in smb.conf

struct smb_perfcount_handlers {
        void (*perfcount_start) (struct smb_perfcount_data *pcd);
        void (*perfcount_add) (struct smb_perfcount_data *pcd);
        void (*perfcount_set_op) (struct smb_perfcount_data *pcd, int op);
        void (*perfcount_set_subop) (struct smb_perfcount_data *pcd, int subop);
        void (*perfcount_set_ioctl) (struct smb_perfcount_data *pcd, int io_ctl);
        void (*perfcount_set_msglen_in) (struct smb_perfcount_data *pcd,
                                         uint64_t in_bytes);
        void (*perfcount_set_msglen_out) (struct smb_perfcount_data *pcd,
                                          uint64_t out_bytes);
        void (*perfcount_copy_context) (struct smb_perfcount_data *pcd,
                                        struct smb_perfcount_data *new_pcd);
        void (*perfcount_defer_op) (struct smb_perfcount_data *pcd,
                                    struct smb_perfcount_data *def_pcd);
        void (*perfcount_end) (struct smb_perfcount_data *pcd);
};

VFS module

vfs objects in smb.conf

https://wiki.samba.org/index.php/Writing_a_Samba_VFS_Module

struct vfs_fn_pointers {
        /* Disk operations */

        int (*connect_fn)(struct vfs_handle_struct *handle, const char *service, const char *user);
        void (*disconnect_fn)(struct vfs_handle_struct *handle);
        uint64_t (*disk_free_fn)(struct vfs_handle_struct *handle, const char *path, bool small_query,
                              uint64_t *bsize, uint64_t *dfree, uint64_t *dsize);
        int (*get_quota_fn)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id,
                              SMB_DISK_QUOTA *qt);
        int (*set_quota_fn)(struct vfs_handle_struct *handle, enum SMB_QUOTA_TYPE qtype, unid_t id,
                              SMB_DISK_QUOTA *qt);
        int (*get_shadow_copy_data_fn)(struct vfs_handle_struct *handle, struct files_struct *fsp,
                              struct shadow_copy_data *shadow_copy_data, bool labels);
        int (*statvfs_fn)(struct vfs_handle_struct *handle, const char *path, struct vfs_statvfs_struct *statbuf);
        uint32_t (*fs_capabilities_fn)(struct vfs_handle_struct *handle, enum timestamp_set_resolution *p_ts_res);


.... more than 100 methods ....

IDMAP PLUGIN

idmap backend in smb.conf

struct idmap_methods {

        /* Called when backend is first loaded */
        NTSTATUS (*init)(struct idmap_domain *dom); 

        /* Map an array of uids/gids to SIDs.  The caller specifies
           the uid/gid and type. Gets back the SID. */
        NTSTATUS (*unixids_to_sids)(struct idmap_domain *dom, struct id_map **ids);

        /* Map an arry of SIDs to uids/gids.  The caller sets the SID
           and type and gets back a uid or gid. */
        NTSTATUS (*sids_to_unixids)(struct idmap_domain *dom, struct id_map **ids);

        /* Allocate a Unix-ID. */
        NTSTATUS (*allocate_id)(struct idmap_domain *dom, struct unixid *id);
};

NSS_INFO PLUGIN

winbind nss info in smb.conf

struct nss_info_methods {
        NTSTATUS (*init)( struct nss_domain_entry *e );
        NTSTATUS (*get_nss_info)( struct nss_domain_entry *e,
                                  const struct dom_sid *sid,
                                  TALLOC_CTX *ctx,
                                  const char **homedir, const char **shell,
                                  const char **gecos, gid_t *p_gid);
        NTSTATUS (*map_to_alias)(TALLOC_CTX *mem_ctx,
                                 struct nss_domain_entry *e,
                                 const char *name, char **alias);
        NTSTATUS (*map_from_alias)(TALLOC_CTX *mem_ctx,
                                   struct nss_domain_entry *e,
                                   const char *alias, char **name);
        NTSTATUS (*close_fn)( void );
};

PASSDB PLUGIN

passdb backend in smb.conf

struct pdb_methods
{
        const char *name; /* What name got this module */

        struct pdb_domain_info *(*get_domain_info)(struct pdb_methods *,
                                                   TALLOC_CTX *mem_ctx);

        NTSTATUS (*getsampwnam)(struct pdb_methods *, struct samu *sam_acct, const char *username);

        NTSTATUS (*getsampwsid)(struct pdb_methods *, struct samu *sam_acct, const struct dom_sid *sid);

        NTSTATUS (*create_user)(struct pdb_methods *, TALLOC_CTX *tmp_ctx,
                                const char *name, uint32_t acct_flags,
                                uint32_t *rid);

        NTSTATUS (*delete_user)(struct pdb_methods *, TALLOC_CTX *tmp_ctx,
                                struct samu *sam_acct);

.... over 60 methods ....

CIFS-Utils iDMAP plugin

/etc/cifs-utils/idmap-plugin

extern int cifs_idmap_init_plugin(void **handle, const char **errmsg);

extern void cifs_idmap_exit_plugin(void *handle);

extern int cifs_idmap_sid_to_str(void *handle, const struct cifs_sid *sid,
                                        char **name);

extern int cifs_idmap_str_to_sid(void *handle, const char *name,
                                struct cifs_sid *sid);

extern int cifs_idmap_sids_to_ids(void *handle, const struct cifs_sid *sid,
                                const size_t num, struct cifs_uxid *cuxid);

extern int cifs_idmap_ids_to_sids(void *handle, const struct cifs_uxid *cuxid,
                                const size_t num, struct cifs_sid *sid);

LDB modules

@LIST attribute in dn: @MODULES

struct ldb_module_ops {
        const char *name;
        int (*init_context) (struct ldb_module *);
        int (*search)(struct ldb_module *, struct ldb_request *); /* search */
        int (*add)(struct ldb_module *, struct ldb_request *); /* add */
        int (*modify)(struct ldb_module *, struct ldb_request *); /* modify */
        int (*del)(struct ldb_module *, struct ldb_request *); /* delete */
        int (*rename)(struct ldb_module *, struct ldb_request *); /* rename */
        int (*request)(struct ldb_module *, struct ldb_request *); /* match any other operation */
        int (*extended)(struct ldb_module *, struct ldb_request *); /* extended operations */
        int (*start_transaction)(struct ldb_module *);
        int (*prepare_commit)(struct ldb_module *);
        int (*end_transaction)(struct ldb_module *);
        int (*del_transaction)(struct ldb_module *);
        int (*sequence_number)(struct ldb_module *, struct ldb_request *);
        void *private_data;
};

LDB BACKENDS

URL in ldb_connect()

struct ldb_module_ops {
        const char *name;
        int (*init_context) (struct ldb_module *);
        int (*search)(struct ldb_module *, struct ldb_request *); /* search */
        int (*add)(struct ldb_module *, struct ldb_request *); /* add */
        int (*modify)(struct ldb_module *, struct ldb_request *); /* modify */
        int (*del)(struct ldb_module *, struct ldb_request *); /* delete */
        int (*rename)(struct ldb_module *, struct ldb_request *); /* rename */
        int (*request)(struct ldb_module *, struct ldb_request *); /* match any other operation */
        int (*extended)(struct ldb_module *, struct ldb_request *); /* extended operations */
        int (*start_transaction)(struct ldb_module *);
        int (*prepare_commit)(struct ldb_module *);
        int (*end_transaction)(struct ldb_module *);
        int (*del_transaction)(struct ldb_module *);
        int (*sequence_number)(struct ldb_module *, struct ldb_request *);
        void *private_data;
};

LDB BACKENDS

Examples foR

Identity plugins

provides

LDAP

KDC

DNS

NTP

CA

MS-RPC

reads from

LDAP

IPA

AD

FreeIPA and TRUST to AD

FreeIPA

Server

FreeIPA

Client

AD DC

AD Client

Trust

FreeIPA and TRUST to AD

IPA PASSDB plugin

implements only a SUB-set of paSsdb calls

UseD to drive trust related RPC calls

implements bind_callback to allow bind with keytab

https://git.fedorahosted.org/cgit/freeipa.git/tree/daemons/ipa-sam

SSSD CIFS-CLIENT plugin

complete implementation

uses SSSD for SID-to-Name and SID-to-ID lookups

Switching possible with /sbin/alternatives

https://git.fedorahosted.org/cgit/sssd.git/tree/src/lib/cifs_idmap_sss

LDB meberof plugin

AddS memberof attribute if user is added to a group

Implements Add, Modify and DEL

https://git.fedorahosted.org/ \

cgit/sssd.git/tree/src/ldb_modules/memberof.c

SSSD's libwbclient.so

Sub-Set of the libwbclient API

authentication, WINS, trust management, ID allocation

uses SSSD for ID-Mapping

Switching possible with /sbin/alternatives

https://git.fedorahosted.org/ \

cgit/sssd.git/tree/src/sss_client/libwbclient

 

SSSD's lOCALAUTH plugin

Check relation between Kerberos principal and login name

Currently nothing Similar in Samba

HeimDAL upstream allows similar plugins

 

https://git.fedorahosted.org/ \

cgit/sssd.git/tree/src/krb5_plugin/sssd_krb5_localauth_plugin.c

If you have to adapt Samba to your product or environment

 

Think about using plugins

Thank you