Ignore:
Timestamp:
May 27, 2009, 9:09:42 AM (16 years ago)
Author:
Herwig Bauernfeind
Message:

Update 3.2 branch to 3.2.8

Location:
branches/samba-3.2.x/source/winbindd
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • branches/samba-3.2.x/source/winbindd/winbindd.c

    r228 r232  
    171171}
    172172
    173 static bool do_sigterm;
     173static SIG_ATOMIC_T do_sigterm = 0;
    174174
    175175static void termination_handler(int signum)
    176176{
    177         do_sigterm = True;
     177        do_sigterm = 1;
    178178        sys_select_signal(signum);
    179179}
    180180
    181 static bool do_sigusr2;
     181static SIG_ATOMIC_T do_sigusr2 = 0;
    182182
    183183static void sigusr2_handler(int signum)
    184184{
    185         do_sigusr2 = True;
     185        do_sigusr2 = 1;
    186186        sys_select_signal(SIGUSR2);
    187187}
    188188
    189 static bool do_sighup;
     189static SIG_ATOMIC_T do_sighup = 0;
    190190
    191191static void sighup_handler(int signum)
    192192{
    193         do_sighup = True;
     193        do_sighup = 1;
    194194        sys_select_signal(SIGHUP);
    195195}
    196196
    197 static bool do_sigchld;
     197static SIG_ATOMIC_T do_sigchld = 0;
    198198
    199199static void sigchld_handler(int signum)
    200200{
    201         do_sigchld = True;
     201        do_sigchld = 1;
    202202        sys_select_signal(SIGCHLD);
    203203}
     
    222222                         DATA_BLOB *data)
    223223{
    224         do_sigterm = True;
     224        do_sigterm = 1;
    225225}
    226226
     
    747747{
    748748        char c = 0;
     749        int nwritten;
    749750
    750751        /* It's a dead client - hold a funeral */
     
    755756
    756757        /* tell client, we are closing ... */
    757         write(state->sock, &c, sizeof(c));
     758        nwritten = write(state->sock, &c, sizeof(c));
     759        if (nwritten == -1) {
     760                DEBUG(2, ("final write to client failed: %s\n",
     761                          strerror(errno)));
     762        }
    758763
    759764        /* Close socket */
     
    823828                reload_services_file(logfile);
    824829
    825                 do_sighup = False;
     830                do_sighup = 0;
    826831        }
    827832}
     
    9981003        if (do_sigusr2) {
    9991004                print_winbindd_status();
    1000                 do_sigusr2 = False;
     1005                do_sigusr2 = 0;
    10011006        }
    10021007
     
    10041009                pid_t pid;
    10051010
    1006                 do_sigchld = False;
     1011                do_sigchld = 0;
    10071012
    10081013                while ((pid = sys_waitpid(-1, NULL, WNOHANG)) > 0) {
     
    12181223        TimeInit();
    12191224
    1220         if (!reinit_after_fork(winbind_messaging_context(), false)) {
     1225        /* Don't use winbindd_reinit_after_fork here as
     1226         * we're just starting up and haven't created any
     1227         * winbindd-specific resources we must free yet. JRA.
     1228         */
     1229
     1230        if (!reinit_after_fork(winbind_messaging_context(),
     1231                               winbind_event_context(), false)) {
    12211232                DEBUG(0,("reinit_after_fork() failed\n"));
    12221233                exit(1);
  • branches/samba-3.2.x/source/winbindd/winbindd_cache.c

    r204 r232  
    487487
    488488        /* see if we have to refetch the domain sequence number */
    489         if (!force && (time_diff < cache_time)) {
     489        if (!force && (time_diff < cache_time) &&
     490                        (domain->sequence_number != DOM_SEQUENCE_NONE) &&
     491                        NT_STATUS_IS_OK(domain->last_status)) {
    490492                DEBUG(10, ("refresh_sequence_number: %s time ok\n", domain->name));
    491493                goto done;
     
    496498       
    497499        status = fetch_cache_seqnum( domain, t );
    498         if ( NT_STATUS_IS_OK(status) )
    499                 goto done;     
     500        if (NT_STATUS_IS_OK(status) &&
     501                        (domain->sequence_number != DOM_SEQUENCE_NONE) &&
     502                        NT_STATUS_IS_OK(domain->last_status)) {
     503                goto done;
     504        }
    500505
    501506        /* important! make sure that we know if this is a native
  • branches/samba-3.2.x/source/winbindd/winbindd_cm.c

    r228 r232  
    174174        pid_t child_pid;
    175175        pid_t parent_pid = sys_getpid();
     176        char *lfile = NULL;
    176177
    177178        /* Stop zombies */
     
    200201        /* Leave messages blocked - we will never process one. */
    201202
    202         if (!reinit_after_fork(winbind_messaging_context(), true)) {
     203        if (!override_logfile) {
     204                if (asprintf(&lfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) == -1) {
     205                        DEBUG(0, ("fork_child_dc_connect: out of memory!\n"));
     206                        _exit(1);
     207                }
     208        }
     209
     210        if (!winbindd_reinit_after_fork(lfile)) {
    203211                DEBUG(0,("reinit_after_fork() failed\n"));
    204                 _exit(0);
    205         }
    206 
    207         close_conns_after_fork();
    208 
    209         if (!override_logfile) {
    210                 char *logfile;
    211                 if (asprintf(&logfile, "%s/log.winbindd-dc-connect", get_dyn_LOGFILEBASE()) > 0) {
    212                         lp_set_logfile(logfile);
    213                         SAFE_FREE(logfile);
    214                         reopen_logs();
    215                 }
    216         }
     212                messaging_send_buf(winbind_messaging_context(),
     213                                   pid_to_procid(parent_pid),
     214                                   MSG_WINBIND_FAILED_TO_GO_ONLINE,
     215                                   (uint8 *)domain->name,
     216                                   strlen(domain->name) + 1);
     217                _exit(1);
     218        }
     219
     220        SAFE_FREE(lfile);
    217221
    218222        mem_ctx = talloc_init("fork_child_dc_connect");
    219223        if (!mem_ctx) {
    220224                DEBUG(0,("talloc_init failed.\n"));
    221                 _exit(0);
     225                _exit(1);
    222226        }
    223227
     
    378382****************************************************************/
    379383
     384void ccache_regain_all_now(void);
     385
    380386static void set_domain_online(struct winbindd_domain *domain)
    381387{
    382         struct timeval now;
    383388
    384389        DEBUG(10,("set_domain_online: called for domain %s\n",
     
    400405
    401406        /* If we are waiting to get a krb5 ticket, trigger immediately. */
    402         GetTimeOfDay(&now);
    403         set_event_dispatch_time(winbind_event_context(),
    404                                 "krb5_ticket_gain_handler", now);
    405 
     407        ccache_regain_all_now();
     408       
    406409        /* Ok, we're out of any startup mode now... */
    407410        domain->startup = False;
     
    475478           Wait at least 5 seconds. Heuristics suck... */
    476479
     480        GetTimeOfDay(&tev);
     481
     482        /* Go into "startup" mode again. */
     483        domain->startup_time = tev.tv_sec;
     484        domain->startup = True;
     485
     486        tev.tv_sec += 5;
    477487        if (!domain->check_online_event) {
    478488                /* If we've come from being globally offline we
     
    480490                   We need to add one now we're trying to go
    481491                   back online. */
    482 
    483492                DEBUG(10,("set_domain_online_request: domain %s was globally offline.\n",
    484493                        domain->name ));
    485 
    486                 domain->check_online_event = event_add_timed(winbind_event_context(),
    487                                                                 NULL,
    488                                                                 timeval_current_ofs(5, 0),
    489                                                                 "check_domain_online_handler",
    490                                                                 check_domain_online_handler,
    491                                                                 domain);
    492 
    493                 /* The above *has* to succeed for winbindd to work. */
    494                 if (!domain->check_online_event) {
    495                         smb_panic("set_domain_online_request: failed to add online handler");
    496                 }
    497         }
    498 
    499         GetTimeOfDay(&tev);
    500 
    501         /* Go into "startup" mode again. */
    502         domain->startup_time = tev.tv_sec;
    503         domain->startup = True;
    504 
    505         tev.tv_sec += 5;
    506 
    507         set_event_dispatch_time(winbind_event_context(), "check_domain_online_handler", tev);
     494        }
     495       
     496        TALLOC_FREE(domain->check_online_event);
     497       
     498        domain->check_online_event = event_add_timed(winbind_event_context(),
     499                                                        NULL,
     500                                                        tev,
     501                                                        "check_domain_online_handler",
     502                                                        check_domain_online_handler,
     503                                                        domain);
     504       
     505        /* The above *has* to succeed for winbindd to work. */
     506        if (!domain->check_online_event) {
     507                smb_panic("set_domain_online_request: failed to add online handler");
     508        }
    508509}
    509510
     
    613614                                                  &domain_info,
    614615                                                  &werr);
    615                 if (W_ERROR_IS_OK(werr)) {
     616                if (NT_STATUS_IS_OK(result) && W_ERROR_IS_OK(werr)) {
    616617                        tmp = talloc_strdup(
    617618                                mem_ctx, domain_info->dc_unc);
  • branches/samba-3.2.x/source/winbindd/winbindd_cred_cache.c

    r133 r232  
    3535
    3636static struct WINBINDD_CCACHE_ENTRY *ccache_list;
     37static void add_krb5_ticket_gain_handler_event(struct WINBINDD_CCACHE_ENTRY *entry,
     38                                                struct timeval t);
    3739
    3840/* The Krb5 ticket refresh handler should be scheduled
     
    7173        return i;
    7274}
     75
     76void ccache_remove_all_after_fork(void)
     77{
     78        struct WINBINDD_CCACHE_ENTRY *cur;
     79        cur = ccache_list;
     80        while (cur) {
     81                DLIST_REMOVE(ccache_list, cur);
     82                TALLOC_FREE(cur->event);
     83                TALLOC_FREE(cur);
     84                cur = ccache_list;
     85        }
     86}
     87
     88static void krb5_ticket_gain_handler(struct event_context *event_ctx,
     89                                     struct timed_event *te,
     90                                     const struct timeval *now,
     91                                     void *private_data);
     92static void krb5_ticket_refresh_handler(struct event_context *event_ctx,
     93                                        struct timed_event *te,
     94                                        const struct timeval *now,
     95                                        void *private_data);
     96
     97void ccache_regain_all_now(void)
     98{
     99        struct WINBINDD_CCACHE_ENTRY *cur;
     100        struct timeval t = timeval_current();
     101
     102        for (cur = ccache_list; cur; cur = cur->next) {
     103                struct timed_event *new_event;
     104
     105                /*
     106                 * if refresh_time is 0, we know that the
     107                 * the event has the krb5_ticket_gain_handler
     108                 */
     109                if (cur->refresh_time == 0) {
     110                        new_event = event_add_timed(winbind_event_context(),
     111                                                      cur, t,
     112                                                      "krb5_ticket_gain_handler",
     113                                                      krb5_ticket_gain_handler,
     114                                                      cur);
     115                } else {
     116                        new_event = event_add_timed(winbind_event_context(),
     117                                                     cur, t,
     118                                                     "krb5_ticket_refresh_handler",
     119                                                     krb5_ticket_refresh_handler,
     120                                                     cur);
     121                }
     122                if (!new_event) {
     123                        continue;
     124                }
     125
     126                TALLOC_FREE(cur->event);
     127                cur->event = new_event;
     128        }
     129        return;
     130}
     131
     132/****************************************************************
     133 The gain initial tikcet case is recongnized as entry->refresh_time
     134 is always zero.
     135****************************************************************/
     136
     137static void add_krb5_ticket_gain_handler_event(struct WINBINDD_CCACHE_ENTRY *entry,
     138                                                struct timeval t)
     139{
     140        entry->refresh_time = 0;
     141        entry->event = event_add_timed(winbind_event_context(), entry,
     142                                        t,
     143                                        "krb5_ticket_gain_handler",
     144                                        krb5_ticket_gain_handler,
     145                                        entry);
     146}
     147
    73148
    74149/****************************************************************
     
    86161        int ret;
    87162        time_t new_start;
     163        time_t expire_time = 0;
    88164        struct WINBINDD_MEMORY_CREDS *cred_ptr = entry->cred_ptr;
    89165#endif
     
    98174
    99175        /* Kinit again if we have the user password and we can't renew the old
    100          * tgt anymore */
    101 
    102         if ((entry->renew_until < time(NULL)) && cred_ptr && cred_ptr->pass) {
    103 
    104                 set_effective_uid(entry->uid);
    105 
    106                 ret = kerberos_kinit_password_ext(entry->principal_name,
    107                                                   cred_ptr->pass,
    108                                                   0, /* hm, can we do time correction here ? */
    109                                                   &entry->refresh_time,
    110                                                   &entry->renew_until,
    111                                                   entry->ccname,
    112                                                   False, /* no PAC required anymore */
    113                                                   True,
    114                                                   WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
    115                                                   NULL);
    116                 gain_root_privilege();
    117 
    118                 if (ret) {
    119                         DEBUG(3,("krb5_ticket_refresh_handler: "
    120                                 "could not re-kinit: %s\n",
    121                                 error_message(ret)));
    122                         TALLOC_FREE(entry->event);
    123                         return;
    124                 }
    125 
    126                 DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit "
    127                         "for: %s in ccache: %s\n",
    128                         entry->principal_name, entry->ccname));
    129 
     176         * tgt anymore
     177         * NB
     178         * This happens when machine are put to sleep for a very long time. */
     179
     180        if (entry->renew_until < time(NULL)) {
     181rekinit:
     182                if (cred_ptr && cred_ptr->pass) {
     183
     184                        set_effective_uid(entry->uid);
     185
     186                        ret = kerberos_kinit_password_ext(entry->principal_name,
     187                                                          cred_ptr->pass,
     188                                                          0, /* hm, can we do time correction here ? */
     189                                                          &entry->refresh_time,
     190                                                          &entry->renew_until,
     191                                                          entry->ccname,
     192                                                          False, /* no PAC required anymore */
     193                                                          True,
     194                                                          WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
     195                                                          NULL);
     196                        gain_root_privilege();
     197
     198                        if (ret) {
     199                                DEBUG(3,("krb5_ticket_refresh_handler: "
     200                                        "could not re-kinit: %s\n",
     201                                        error_message(ret)));
     202                                /* destroy the ticket because we cannot rekinit
     203                                 * it, ignore error here */
     204                                ads_kdestroy(entry->ccname);
     205
     206                                /* Don't break the ticket refresh chain: retry
     207                                 * refreshing ticket sometime later when KDC is
     208                                 * unreachable -- BoYang
     209                                 * */
     210
     211                                if ((ret == KRB5_KDC_UNREACH)
     212                                    || (ret == KRB5_REALM_CANT_RESOLVE)) {
    130213#if defined(DEBUG_KRB5_TKT_RENEWAL)
    131                 new_start = time(NULL) + 30;
    132 #else
    133                 /* The tkt should be refreshed at one-half the period
    134                    from now to the expiration time */
    135                 new_start = KRB5_EVENT_REFRESH_TIME(entry->refresh_time);
    136 #endif
    137                 goto done;
     214                                        new_start = time(NULL) + 30;
     215#else
     216                                        new_start = time(NULL) +
     217                                                    MAX(30, lp_winbind_cache_time());
     218#endif
     219                                        /* try to regain ticket here */
     220                                        add_krb5_ticket_gain_handler_event(entry,
     221                                                                           timeval_set(new_start, 0));
     222                                        return;
     223                                }
     224                                TALLOC_FREE(entry->event);
     225                                return;
     226                        }
     227
     228                        DEBUG(10,("krb5_ticket_refresh_handler: successful re-kinit "
     229                                "for: %s in ccache: %s\n",
     230                                entry->principal_name, entry->ccname));
     231
     232#if defined(DEBUG_KRB5_TKT_RENEWAL)
     233                        new_start = time(NULL) + 30;
     234#else
     235                        /* The tkt should be refreshed at one-half the period
     236                           from now to the expiration time */
     237                        expire_time = entry->refresh_time;
     238                        new_start = KRB5_EVENT_REFRESH_TIME(entry->refresh_time);
     239#endif
     240                        goto done;
     241                } else {
     242                                /* can this happen?
     243                                 * No cached credentials
     244                                 * destroy ticket and refresh chain
     245                                 * */
     246                                ads_kdestroy(entry->ccname);
     247                                TALLOC_FREE(entry->event);
     248                                return;
     249                }
    138250        }
    139251
     
    147259        new_start = time(NULL) + 30;
    148260#else
     261        expire_time = new_start;
    149262        new_start = KRB5_EVENT_REFRESH_TIME(new_start);
    150263#endif
     
    158271                /* maybe we are beyond the renewing window */
    159272
     273                /* evil rises here, we refresh ticket failed,
     274                 * but the ticket might be expired. Therefore,
     275                 * When we refresh ticket failed, destory the
     276                 * ticket */
     277
     278                ads_kdestroy(entry->ccname);
     279
    160280                /* avoid breaking the renewal chain: retry in
    161281                 * lp_winbind_cache_time() seconds when the KDC was not
    162                  * available right now. */
    163 
    164                 if (ret == KRB5_KDC_UNREACH) {
     282                 * available right now.
     283                 * the return code can be KRB5_REALM_CANT_RESOLVE*/
     284
     285                if ((ret == KRB5_KDC_UNREACH)
     286                    || (ret == KRB5_REALM_CANT_RESOLVE)) {
     287#if defined(DEBUG_KRB5_TKT_RENEWAL)
     288                        new_start = time(NULL) + 30;
     289#else
    165290                        new_start = time(NULL) +
    166291                                    MAX(30, lp_winbind_cache_time());
    167                         goto done;
    168                 }
     292#endif
     293                        /* ticket is destroyed here, we have to regain it
     294                         * if it is possible */
     295                        add_krb5_ticket_gain_handler_event(entry,
     296                                                           timeval_set(new_start, 0));
     297                        return;
     298                }
     299
     300                /* This is evil, if the ticket was already expired.
     301                 * renew ticket function returns KRB5KRB_AP_ERR_TKT_EXPIRED.
     302                 * But there is still a chance that we can rekinit it.
     303                 *
     304                 * This happens when user login in online mode, and then network
     305                 * down or something cause winbind goes offline for a very long time,
     306                 * and then goes online again. ticket expired, renew failed.
     307                 * This happens when machine are put to sleep for a long time,
     308                 * but shorter than entry->renew_util.
     309                 * NB
     310                 * Looks like the KDC is reachable, we want to rekinit as soon as
     311                 * possible instead of waiting some time later. */
     312                if ((ret == KRB5KRB_AP_ERR_TKT_EXPIRED)
     313                    || (ret == KRB5_FCC_NOFILE)) goto rekinit;
    169314
    170315                return;
     
    172317
    173318done:
    174 
     319        /* in cases that ticket will be unrenewable soon, we don't try to renew ticket
     320         * but try to regain ticket if it is possible */
     321        if (entry->renew_until && expire_time
     322             && (entry->renew_until <= expire_time)) {
     323                /* try to regain ticket 10 seconds beforre expiration */
     324                expire_time -= 10;
     325                add_krb5_ticket_gain_handler_event(entry, timeval_set(expire_time, 0));
     326                return;
     327        }
     328
     329        if (!entry->refresh_time) {
     330                entry->refresh_time = new_start;
     331        }
    175332        entry->event = event_add_timed(winbind_event_context(), entry,
    176333                                       timeval_set(new_start, 0),
     
    240397                        "could not kinit: %s\n",
    241398                        error_message(ret)));
     399                /* evil. If we cannot do it, destroy any the __maybe__
     400                 * __existing__ ticket */
     401                ads_kdestroy(entry->ccname);
    242402                goto retry_later;
    243403        }
     
    250410
    251411  retry_later:
    252 
     412 
     413#if defined(DEBUG_KRB5_TKT_REGAIN)
     414        t = timeval_set(time(NULL) + 30, 0);
     415#else
    253416        t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0);
    254 
    255         entry->event = event_add_timed(winbind_event_context(),
    256                                        entry,
    257                                        t,
    258                                        "krb5_ticket_gain_handler",
    259                                        krb5_ticket_gain_handler,
    260                                        entry);
     417#endif
     418
     419        add_krb5_ticket_gain_handler_event(entry, t);
    261420
    262421        return;
     
    270429#endif
    271430
     431        if (!entry->refresh_time) {
     432                entry->refresh_time = t.tv_sec;
     433        }
    272434        entry->event = event_add_timed(winbind_event_context(),
    273435                                       entry,
     
    332494        struct WINBINDD_CCACHE_ENTRY *entry = NULL;
    333495        struct timeval t;
     496        NTSTATUS ntret;
     497#ifdef HAVE_KRB5
     498        int ret;
     499#endif
    334500
    335501        if ((username == NULL && princ_name == NULL) ||
     
    343509                return NT_STATUS_NO_MORE_ENTRIES;
    344510        }
     511
     512        /* If it is cached login, destroy krb5 ticket
     513         * to avoid surprise. */
     514#ifdef HAVE_KRB5
     515        if (postponed_request) {
     516                /* ignore KRB5_FCC_NOFILE error here */
     517                ret = ads_kdestroy(ccname);
     518                if (ret == KRB5_FCC_NOFILE) {
     519                        ret = 0;
     520                }
     521                if (ret) {
     522                        DEBUG(0, ("add_ccache_to_list: failed to destroy "
     523                                   "user krb5 ccache %s with %s\n", ccname,
     524                                   error_message(ret)));
     525                        return krb5_to_nt_status(ret);
     526                } else {
     527                        DEBUG(10, ("add_ccache_to_list: successfully destroyed "
     528                                   "krb5 ccache %s for user %s\n", ccname,
     529                                   username));
     530                }
     531        }
     532#endif
    345533
    346534        /* Reference count old entries */
     
    356544                        username, entry->ref_count));
    357545                /* FIXME: in this case we still might want to have a krb5 cred
    358                  * event handler created - gd*/
     546                 * event handler created - gd
     547                 * Add ticket refresh handler here */
     548               
     549                if (!lp_winbind_refresh_tickets() || renew_until <= 0) {
     550                        return NT_STATUS_OK;
     551                }
     552               
     553                if (!entry->event) {
     554                        if (postponed_request) {
     555                                t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0);
     556                                add_krb5_ticket_gain_handler_event(entry, t);
     557                        } else {
     558                                /* Renew at 1/2 the ticket expiration time */
     559#if defined(DEBUG_KRB5_TKT_RENEWAL)
     560                                t = timeval_set(time(NULL)+30, 0);
     561#else
     562                                t = timeval_set(KRB5_EVENT_REFRESH_TIME(ticket_end), 0);
     563#endif
     564                                if (!entry->refresh_time) {
     565                                        entry->refresh_time = t.tv_sec;
     566                                }
     567                                entry->event = event_add_timed(winbind_event_context(),
     568                                                               entry,
     569                                                               t,
     570                                                               "krb5_ticket_refresh_handler",
     571                                                               krb5_ticket_refresh_handler,
     572                                                               entry);
     573                        }
     574
     575                        if (!entry->event) {
     576                                ntret = remove_ccache(username);
     577                                if (!NT_STATUS_IS_OK(ntret)) {
     578                                        DEBUG(0, ("add_ccache_to_list: Failed to remove krb5 "
     579                                                  "ccache %s for user %s\n", entry->ccname,
     580                                                  entry->username));
     581                                        DEBUG(0, ("add_ccache_to_list: error is %s\n",
     582                                                  nt_errstr(ntret)));
     583                                        return ntret;
     584                                }
     585                                return NT_STATUS_NO_MEMORY;
     586                        }
     587
     588                        DEBUG(10,("add_ccache_to_list: added krb5_ticket handler\n"));
     589                }
     590                 
    359591                return NT_STATUS_OK;
    360592        }
     
    407639        if (postponed_request) {
    408640                t = timeval_current_ofs(MAX(30, lp_winbind_cache_time()), 0);
    409                 entry->event = event_add_timed(winbind_event_context(),
    410                                                entry,
    411                                                t,
    412                                                "krb5_ticket_gain_handler",
    413                                                krb5_ticket_gain_handler,
    414                                                entry);
     641                add_krb5_ticket_gain_handler_event(entry, t);
    415642        } else {
    416643                /* Renew at 1/2 the ticket expiration time */
     
    420647                t = timeval_set(KRB5_EVENT_REFRESH_TIME(ticket_end), 0);
    421648#endif
     649                if (!entry->refresh_time) {
     650                        entry->refresh_time = t.tv_sec;
     651                }
     652               
    422653                entry->event = event_add_timed(winbind_event_context(),
    423654                                               entry,
  • branches/samba-3.2.x/source/winbindd/winbindd_dual.c

    r228 r232  
    881881{
    882882        struct winbindd_domain *domain;
     883        struct winbindd_domain *primary_domain = NULL;
    883884        const char *domainname = (const char *)data->data;
    884885
     
    893894                return;
    894895        }
     896
     897        primary_domain = find_our_domain();
    895898
    896899        /* Mark the requested domain offline. */
     
    903906                        DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
    904907                        set_domain_offline(domain);
     908                        /* we are in the trusted domain, set the primary domain
     909                         * offline too */
     910                        if (domain != primary_domain) {
     911                                set_domain_offline(primary_domain);
     912                        }
    905913                }
    906914        }
     
    916924{
    917925        struct winbindd_domain *domain;
     926        struct winbindd_domain *primary_domain = NULL;
    918927        const char *domainname = (const char *)data->data;
    919928
     
    928937                return;
    929938        }
     939
     940        primary_domain = find_our_domain();
    930941
    931942        /* Set our global state as online. */
     
    943954                        winbindd_flush_negative_conn_cache(domain);
    944955                        set_domain_online_request(domain);
     956
     957                        /* we can be in trusted domain, which will contact primary domain
     958                         * we have to bring primary domain online in trusted domain process
     959                         * see, winbindd_dual_pam_auth() --> winbindd_dual_pam_auth_samlogon()
     960                         * --> contact_domain = find_our_domain()
     961                         * */
     962                        if (domain != primary_domain) {
     963                                winbindd_flush_negative_conn_cache(primary_domain);
     964                                set_domain_online_request(primary_domain);
     965                        }
    945966                }
    946967        }
     
    10201041}
    10211042
    1022 
    1023 static bool fork_domain_child(struct winbindd_child *child)
    1024 {
    1025         int fdpair[2];
    1026         struct winbindd_cli_state state;
     1043void ccache_remove_all_after_fork(void);
     1044
     1045bool winbindd_reinit_after_fork(const char *logfilename)
     1046{
    10271047        struct winbindd_domain *domain;
    1028         struct winbindd_domain *primary_domain = NULL;
    1029 
    1030         if (child->domain) {
    1031                 DEBUG(10, ("fork_domain_child called for domain '%s'\n",
    1032                            child->domain->name));
    1033         } else {
    1034                 DEBUG(10, ("fork_domain_child called without domain.\n"));
    1035         }
    1036 
    1037         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
    1038                 DEBUG(0, ("Could not open child pipe: %s\n",
    1039                           strerror(errno)));
    1040                 return False;
    1041         }
    1042 
    1043         ZERO_STRUCT(state);
    1044         state.pid = sys_getpid();
    1045 
    1046         child->pid = sys_fork();
    1047 
    1048         if (child->pid == -1) {
    1049                 DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
    1050                 return False;
    1051         }
    1052 
    1053         if (child->pid != 0) {
    1054                 /* Parent */
    1055                 close(fdpair[0]);
    1056                 child->next = child->prev = NULL;
    1057                 DLIST_ADD(children, child);
    1058                 child->event.fd = fdpair[1];
    1059                 child->event.flags = 0;
    1060                 child->requests = NULL;
    1061                 add_fd_event(&child->event);
    1062                 return True;
    1063         }
    1064 
    1065         /* Child */
    1066 
    1067         /* Stop zombies in children */
    1068         CatchChild();
    1069 
    1070         state.sock = fdpair[0];
    1071         close(fdpair[1]);
    1072 
    1073         if (!reinit_after_fork(winbind_messaging_context(), true)) {
     1048        struct winbindd_child *cl;
     1049
     1050        if (!reinit_after_fork(winbind_messaging_context(),
     1051                               winbind_event_context(), true)) {
    10741052                DEBUG(0,("reinit_after_fork() failed\n"));
    1075                 _exit(0);
     1053                return false;
    10761054        }
    10771055
    10781056        close_conns_after_fork();
    10791057
    1080         if (!override_logfile) {
    1081                 lp_set_logfile(child->logfilename);
     1058        if (!override_logfile && logfilename) {
     1059                lp_set_logfile(logfilename);
    10821060                reopen_logs();
    10831061        }
    1084 
    1085         /*
    1086          * For clustering, we need to re-init our ctdbd connection after the
    1087          * fork
    1088          */
    1089         if (!NT_STATUS_IS_OK(messaging_reinit(winbind_messaging_context())))
    1090                 exit(1);
    10911062
    10921063        /* Don't handle the same messages as our parent. */
     
    11081079                             MSG_DEBUG, NULL);
    11091080
    1110         /* Handle online/offline messages. */
    1111         messaging_register(winbind_messaging_context(), NULL,
    1112                            MSG_WINBIND_OFFLINE, child_msg_offline);
    1113         messaging_register(winbind_messaging_context(), NULL,
    1114                            MSG_WINBIND_ONLINE, child_msg_online);
    1115         messaging_register(winbind_messaging_context(), NULL,
    1116                            MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus);
    1117         messaging_register(winbind_messaging_context(), NULL,
    1118                            MSG_DUMP_EVENT_LIST, child_msg_dump_event_list);
    1119         messaging_register(winbind_messaging_context(), NULL,
    1120                            MSG_DEBUG, debug_message);
    1121 
     1081        /* We have destroyed all events in the winbindd_event_context
     1082         * in reinit_after_fork(), so clean out all possible pending
     1083         * event pointers. */
     1084
     1085        /* Deal with check_online_events. */
     1086
     1087        for (domain = domain_list(); domain; domain = domain->next) {
     1088                TALLOC_FREE(domain->check_online_event);
     1089        }
     1090
     1091        /* Ensure we're not handling a credential cache event inherited
     1092         * from our parent. */
     1093
     1094        ccache_remove_all_after_fork();
     1095
     1096        /* Destroy all possible events in child list. */
     1097        for (cl = children; cl != NULL; cl = cl->next) {
     1098                struct winbindd_async_request *request;
     1099
     1100                for (request = cl->requests; request; request = request->next) {
     1101                        TALLOC_FREE(request->reply_timeout_event);
     1102                }
     1103                TALLOC_FREE(cl->lockout_policy_event);
     1104
     1105                /* Children should never be able to send
     1106                 * each other messages, all messages must
     1107                 * go through the parent.
     1108                 */
     1109                cl->pid = (pid_t)0;
     1110        }
     1111        /*
     1112         * This is a little tricky, children must not
     1113         * send an MSG_WINBIND_ONLINE message to idmap_child().
     1114         * If we are in a child of our primary domain or
     1115         * in the process created by fork_child_dc_connect(),
     1116         * and the primary domain cannot go online,
     1117         * fork_child_dc_connection() sends MSG_WINBIND_ONLINE
     1118         * periodically to idmap_child().
     1119         *
     1120         * The sequence is, fork_child_dc_connect() ---> getdcs() --->
     1121         * get_dc_name_via_netlogon() ---> cm_connect_netlogon()
     1122         * ---> init_dc_connection() ---> cm_open_connection --->
     1123         * set_domain_online(), sends MSG_WINBIND_ONLINE to
     1124         * idmap_child(). Disallow children sending messages
     1125         * to each other, all messages must go through the parent.
     1126         */
     1127        cl = idmap_child();
     1128        cl->pid = (pid_t)0;
     1129
     1130        return true;
     1131}
     1132
     1133static bool fork_domain_child(struct winbindd_child *child)
     1134{
     1135        int fdpair[2];
     1136        struct winbindd_cli_state state;
     1137        struct winbindd_domain *primary_domain = NULL;
     1138
     1139        if (child->domain) {
     1140                DEBUG(10, ("fork_domain_child called for domain '%s'\n",
     1141                           child->domain->name));
     1142        } else {
     1143                DEBUG(10, ("fork_domain_child called without domain.\n"));
     1144        }
     1145
     1146        if (socketpair(AF_UNIX, SOCK_STREAM, 0, fdpair) != 0) {
     1147                DEBUG(0, ("Could not open child pipe: %s\n",
     1148                          strerror(errno)));
     1149                return False;
     1150        }
     1151
     1152        ZERO_STRUCT(state);
     1153        state.pid = sys_getpid();
     1154
     1155        child->pid = sys_fork();
     1156
     1157        if (child->pid == -1) {
     1158                DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
     1159                return False;
     1160        }
     1161
     1162        if (child->pid != 0) {
     1163                /* Parent */
     1164                close(fdpair[0]);
     1165                child->next = child->prev = NULL;
     1166                DLIST_ADD(children, child);
     1167                child->event.fd = fdpair[1];
     1168                child->event.flags = 0;
     1169                add_fd_event(&child->event);
     1170                return True;
     1171        }
     1172
     1173        /* Child */
     1174
     1175        /* Stop zombies in children */
     1176        CatchChild();
     1177
     1178        state.sock = fdpair[0];
     1179        close(fdpair[1]);
     1180
     1181        if (!winbindd_reinit_after_fork(child->logfilename)) {
     1182                DEBUG(0, ("winbindd_reinit_after_fork failed.\n"));
     1183                _exit(0);
     1184        }
     1185 
     1186        /* Handle online/offline messages. */
     1187        messaging_register(winbind_messaging_context(), NULL,
     1188                           MSG_WINBIND_OFFLINE, child_msg_offline);
     1189        messaging_register(winbind_messaging_context(), NULL,
     1190                           MSG_WINBIND_ONLINE, child_msg_online);
     1191        messaging_register(winbind_messaging_context(), NULL,
     1192                           MSG_WINBIND_ONLINESTATUS, child_msg_onlinestatus);
     1193        messaging_register(winbind_messaging_context(), NULL,
     1194                           MSG_DUMP_EVENT_LIST, child_msg_dump_event_list);
     1195        messaging_register(winbind_messaging_context(), NULL,
     1196                           MSG_DEBUG, debug_message);
     1197       
     1198        primary_domain = find_our_domain();
     1199
     1200        if (primary_domain == NULL) {
     1201                smb_panic("no primary domain found");
     1202        }
     1203
     1204        /* It doesn't matter if we allow cache login,
     1205         * try to bring domain online after fork. */
    11221206        if ( child->domain ) {
    11231207                child->domain->startup = True;
    11241208                child->domain->startup_time = time(NULL);
    1125         }
    1126 
    1127         /* Ensure we have no pending check_online events other
    1128            than one for this domain or the primary domain. */
    1129 
    1130         for (domain = domain_list(); domain; domain = domain->next) {
    1131                 if (domain->primary) {
    1132                         primary_domain = domain;
    1133                 }
    1134                 if ((domain != child->domain) && !domain->primary) {
    1135                         TALLOC_FREE(domain->check_online_event);
    1136                 }
    1137         }
    1138 
    1139         /* Ensure we're not handling an event inherited from
    1140            our parent. */
    1141 
    1142         cancel_named_event(winbind_event_context(),
    1143                            "krb5_ticket_refresh_handler");
     1209                /* we can be in primary domain or in trusted domain
     1210                 * If we are in trusted domain, set the primary domain
     1211                 * in start-up mode */
     1212                if (!(child->domain->internal)) {
     1213                        set_domain_online_request(child->domain);
     1214                        if (!(child->domain->primary)) {
     1215                                primary_domain->startup = True;
     1216                                primary_domain->startup_time = time(NULL);
     1217                                set_domain_online_request(primary_domain);
     1218                        }
     1219                }
     1220        }
     1221       
     1222        /*
     1223         * We are in idmap child, make sure that we set the
     1224         * check_online_event to bring primary domain online.
     1225         */
     1226        if (child == idmap_child()) {
     1227                set_domain_online_request(primary_domain);
     1228        }
    11441229
    11451230        /* We might be in the idmap child...*/
     
    12251310                        TALLOC_FREE(frame);
    12261311                        perror("select");
    1227                         return False;
     1312                        _exit(1);
    12281313                }
    12291314
     
    12331318                if (state.finished) {
    12341319                        /* we lost contact with our parent */
    1235                         exit(0);
     1320                        _exit(0);
    12361321                }
    12371322
  • branches/samba-3.2.x/source/winbindd/winbindd_util.c

    r228 r232  
    507507{
    508508        time_t now = time(NULL);
    509        
     509
     510        /* Check that we allow trusted domains at all */
     511        if (!lp_allow_trusted_domains())
     512                return;
     513
    510514        /* see if the time has come... */
    511515       
     
    763767        DOM_SID dom_sid;
    764768        uint32 rid;
    765        
     769
     770        /* Check if we even care */
     771
     772        if (!lp_allow_trusted_domains())
     773                return;
     774
    766775        domain = find_domain_from_name_noinit( name );
    767776        if ( domain )
Note: See TracChangeset for help on using the changeset viewer.