99
1010#include <wbclient.h>
1111
12+ #ifdef HAVE_PTHREAD
13+ #include <pthread.h>
14+
15+ static pthread_key_t key ;
16+ static pthread_once_t key_once = PTHREAD_ONCE_INIT ;
17+
18+ /* note that the destructor is given directly the content of the key in
19+ * ptr, not the key itself. */
20+ static void key_destructor (void * ptr )
21+ {
22+ wbcCtxFree ((struct wbcContext * )ptr );
23+ }
24+
25+ static void key_create (void )
26+ {
27+ /* we have no way to report errors ... */
28+ (void )pthread_key_create (& key , key_destructor );
29+ }
30+
31+ static struct wbcContext * winbind_get_context (void )
32+ {
33+ struct wbcContext * ctx ;
34+ int ret ;
35+
36+ ret = pthread_once (& key_once , key_create );
37+ if (ret != 0 ) {
38+ return NULL ;
39+ }
40+ ctx = pthread_getspecific (key );
41+ if (ctx == NULL ) {
42+ ctx = wbcCtxCreate ();
43+ ret = pthread_setspecific (key , ctx );
44+ if (ret != 0 ) {
45+ wbcCtxFree (ctx );
46+ ctx = NULL ;
47+ }
48+ }
49+ return ctx ;
50+ }
51+
52+ #else /* HAVE_PTHREAD */
53+
54+ /* non thread-safe version */
55+ static struct wbcContext * gctx = NULL ;
56+
57+ static struct wbcContext * winbind_get_context (void )
58+ {
59+ if (gctx == NULL ) {
60+ gctx = wbcCtxCreate ();
61+ }
62+ return gctx ;
63+ }
64+ #endif /* HAVE_PTHREAD */
65+
1266uint32_t winbind_get_names (char * * computer , char * * domain )
1367{
68+ struct wbcContext * ctx ;
1469 struct wbcInterfaceDetails * details = NULL ;
1570 wbcErr wbc_status ;
1671 int ret = ERR_NOTAVAIL ;
1772
18- wbc_status = wbcInterfaceDetails (& details );
73+ ctx = winbind_get_context ();
74+ if (ctx == NULL ) {
75+ ret = ERR_BADCTX ;
76+ goto done ;
77+ }
78+
79+ wbc_status = wbcCtxInterfaceDetails (ctx , & details );
1980 if (!WBC_ERROR_IS_OK (wbc_status )) goto done ;
2081
2182 if (computer &&
@@ -51,17 +112,24 @@ uint32_t winbind_get_names(char **computer, char **domain)
51112uint32_t winbind_get_creds (struct gssntlm_name * name ,
52113 struct gssntlm_cred * cred )
53114{
115+ struct wbcContext * ctx ;
54116 struct wbcCredentialCacheParams params ;
55117 struct wbcCredentialCacheInfo * result ;
56118 struct wbcInterfaceDetails * details = NULL ;
57119 wbcErr wbc_status ;
58120 bool cached = false;
59121 int ret = ERR_NOTAVAIL ;
60122
123+ ctx = winbind_get_context ();
124+ if (ctx == NULL ) {
125+ ret = ERR_BADCTX ;
126+ goto done ;
127+ }
128+
61129 if (name && name -> data .user .domain ) {
62130 params .domain_name = name -> data .user .domain ;
63131 } else {
64- wbc_status = wbcInterfaceDetails ( & details );
132+ wbc_status = wbcCtxInterfaceDetails ( ctx , & details );
65133 if (!WBC_ERROR_IS_OK (wbc_status )) goto done ;
66134
67135 params .domain_name = details -> netbios_domain ;
@@ -80,7 +148,7 @@ uint32_t winbind_get_creds(struct gssntlm_name *name,
80148 params .level = WBC_CREDENTIAL_CACHE_LEVEL_NTLMSSP ;
81149 params .num_blobs = 0 ;
82150 params .blobs = NULL ;
83- wbc_status = wbcCredentialCache ( & params , & result , NULL );
151+ wbc_status = wbcCtxCredentialCache ( ctx , & params , & result , NULL );
84152
85153 if (WBC_ERROR_IS_OK (wbc_status )) {
86154 /* Yes, winbind seems to think it has credentials for us */
@@ -120,6 +188,7 @@ uint32_t winbind_cli_auth(char *user, char *domain,
120188 struct ntlm_key * exported_session_key )
121189{
122190 /* Get responses and session key from winbind */
191+ struct wbcContext * ctx ;
123192 struct wbcCredentialCacheParams params ;
124193 struct wbcCredentialCacheInfo * result = NULL ;
125194 struct wbcNamedBlob * sesskey_blob = NULL ;
@@ -130,6 +199,12 @@ uint32_t winbind_cli_auth(char *user, char *domain,
130199 int ret ;
131200 int i ;
132201
202+ ctx = winbind_get_context ();
203+ if (ctx == NULL ) {
204+ ret = ERR_BADCTX ;
205+ goto done ;
206+ }
207+
133208 if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) {
134209 /* Winbind doesn't support this (yet). We'd want to pass our
135210 * own client_target_info in with the request. */
@@ -167,7 +242,7 @@ uint32_t winbind_cli_auth(char *user, char *domain,
167242 }
168243 }
169244
170- wbc_status = wbcCredentialCache ( & params , & result , NULL );
245+ wbc_status = wbcCtxCredentialCache ( ctx , & params , & result , NULL );
171246 if (!WBC_ERROR_IS_OK (wbc_status )) {
172247 ret = ERR_NOTAVAIL ;
173248 goto done ;
@@ -295,6 +370,7 @@ uint32_t winbind_srv_auth(char *user, char *domain,
295370 struct ntlm_key * ntlmv2_key ,
296371 struct gssntlm_name_attribute * * auth_attrs )
297372{
373+ struct wbcContext * ctx ;
298374 struct wbcAuthUserParams wbc_params = { 0 };
299375 struct wbcAuthUserInfo * wbc_info = NULL ;
300376 struct wbcAuthErrorInfo * wbc_err = NULL ;
@@ -306,6 +382,11 @@ uint32_t winbind_srv_auth(char *user, char *domain,
306382 return ERR_KEYLEN ;
307383 }
308384
385+ ctx = winbind_get_context ();
386+ if (ctx == NULL ) {
387+ return ERR_BADCTX ;
388+ }
389+
309390 wbc_params .account_name = user ;
310391 wbc_params .domain_name = domain ;
311392 wbc_params .workstation_name = workstation ;
@@ -320,7 +401,8 @@ uint32_t winbind_srv_auth(char *user, char *domain,
320401 wbc_params .password .response .lm_length = lm_chal_resp -> length ;
321402 wbc_params .password .response .lm_data = lm_chal_resp -> data ;
322403
323- wbc_status = wbcAuthenticateUserEx (& wbc_params , & wbc_info , & wbc_err );
404+ wbc_status = wbcCtxAuthenticateUserEx (ctx , & wbc_params , & wbc_info ,
405+ & wbc_err );
324406
325407 if (!WBC_ERROR_IS_OK (wbc_status )) {
326408 /* TODO: use wbcErrorString, to save error message */
0 commit comments