Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source4/kdc/kpasswdd.c

    r414 r745  
    1 /* 
     1/*
    22   Unix SMB/CIFS implementation.
    33
     
    1111   the Free Software Foundation; either version 3 of the License, or
    1212   (at your option) any later version.
    13    
     13
    1414   This program is distributed in the hope that it will be useful,
    1515   but WITHOUT ANY WARRANTY; without even the implied warranty of
    1616   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1717   GNU General Public License for more details.
    18    
     18
    1919   You should have received a copy of the GNU General Public License
    2020   along with this program.  If not, see <http://www.gnu.org/licenses/>.
     
    2323#include "includes.h"
    2424#include "smbd/service_task.h"
    25 #include "lib/events/events.h"
    26 #include "lib/socket/socket.h"
    27 #include "system/network.h"
    28 #include "../lib/util/dlinklist.h"
    29 #include "lib/ldb/include/ldb.h"
    3025#include "auth/gensec/gensec.h"
    3126#include "auth/credentials/credentials.h"
    32 #include "auth/credentials/credentials_krb5.h"
    3327#include "auth/auth.h"
    3428#include "dsdb/samdb/samdb.h"
    35 #include "rpc_server/dcerpc_server.h"
    36 #include "rpc_server/samr/proto.h"
     29#include "../lib/util/util_ldb.h"
    3730#include "libcli/security/security.h"
    3831#include "param/param.h"
    39 #include "kdc/kdc.h"
    40 
    41 /* TODO: remove all SAMBA4_INTERNAL_HEIMDAL stuff from this file */
    42 #ifdef SAMBA4_INTERNAL_HEIMDAL
    43 #include "heimdal_build/kpasswdd-glue.h"
    44 #endif
    45 
    46 /* hold information about one kdc socket */
    47 struct kpasswd_socket {
    48         struct socket_context *sock;
    49         struct kdc_server *kdc;
    50         struct tevent_fd *fde;
    51 
    52         /* a queue of outgoing replies that have been deferred */
    53         struct kdc_reply *send_queue;
    54 };
     32#include "kdc/kdc-glue.h"
    5533
    5634/* Return true if there is a valid error packet formed in the error_blob */
    57 static bool kpasswdd_make_error_reply(struct kdc_server *kdc, 
    58                                      TALLOC_CTX *mem_ctx, 
    59                                      uint16_t result_code, 
    60                                      const char *error_string, 
    61                                      DATA_BLOB *error_blob) 
     35static bool kpasswdd_make_error_reply(struct kdc_server *kdc,
     36                                     TALLOC_CTX *mem_ctx,
     37                                     uint16_t result_code,
     38                                     const char *error_string,
     39                                     DATA_BLOB *error_blob)
    6240{
    6341        char *error_string_utf8;
    6442        size_t len;
    65        
     43
    6644        DEBUG(result_code ? 3 : 10, ("kpasswdd: %s\n", error_string));
    6745
     
    8058
    8159/* Return true if there is a valid error packet formed in the error_blob */
    82 static bool kpasswdd_make_unauth_error_reply(struct kdc_server *kdc, 
    83                                             TALLOC_CTX *mem_ctx, 
    84                                             uint16_t result_code, 
    85                                             const char *error_string, 
    86                                             DATA_BLOB *error_blob) 
     60static bool kpasswdd_make_unauth_error_reply(struct kdc_server *kdc,
     61                                            TALLOC_CTX *mem_ctx,
     62                                            uint16_t result_code,
     63                                            const char *error_string,
     64                                            DATA_BLOB *error_blob)
    8765{
    8866        bool ret;
     
    9068        DATA_BLOB error_bytes;
    9169        krb5_data k5_error_bytes, k5_error_blob;
    92         ret = kpasswdd_make_error_reply(kdc, mem_ctx, result_code, error_string, 
     70        ret = kpasswdd_make_error_reply(kdc, mem_ctx, result_code, error_string,
    9371                                       &error_bytes);
    9472        if (!ret) {
     
    9876        k5_error_bytes.length = error_bytes.length;
    9977        kret = krb5_mk_error(kdc->smb_krb5_context->krb5_context,
    100                              result_code, NULL, &k5_error_bytes, 
     78                             result_code, NULL, &k5_error_bytes,
    10179                             NULL, NULL, NULL, NULL, &k5_error_blob);
    10280        if (kret) {
     
    11189}
    11290
    113 static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc, 
    114                                         TALLOC_CTX *mem_ctx, 
    115                                         NTSTATUS status, 
    116                                         enum samr_RejectReason reject_reason,
     91static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc,
     92                                        TALLOC_CTX *mem_ctx,
     93                                        NTSTATUS status,
     94                                        enum samPwdChangeReason reject_reason,
    11795                                        struct samr_DomInfo1 *dominfo,
    118                                         DATA_BLOB *error_blob) 
     96                                        DATA_BLOB *error_blob)
    11997{
    12098        if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
    121                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     99                return kpasswdd_make_error_reply(kdc, mem_ctx,
    122100                                                KRB5_KPASSWD_ACCESSDENIED,
    123101                                                "No such user when changing password",
     
    125103        }
    126104        if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
    127                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     105                return kpasswdd_make_error_reply(kdc, mem_ctx,
    128106                                                KRB5_KPASSWD_ACCESSDENIED,
    129107                                                "Not permitted to change password",
     
    133111                const char *reject_string;
    134112                switch (reject_reason) {
    135                 case SAMR_REJECT_TOO_SHORT:
     113                case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT:
    136114                        reject_string = talloc_asprintf(mem_ctx, "Password too short, password must be at least %d characters long",
    137115                                                        dominfo->min_password_length);
    138116                        break;
    139                 case SAMR_REJECT_COMPLEXITY:
     117                case SAM_PWD_CHANGE_NOT_COMPLEX:
    140118                        reject_string = "Password does not meet complexity requirements";
    141119                        break;
    142                 case SAMR_REJECT_IN_HISTORY:
     120                case SAM_PWD_CHANGE_PWD_IN_HISTORY:
    143121                        reject_string = "Password is already in password history";
    144122                        break;
    145                 case SAMR_REJECT_OTHER:
    146123                default:
    147124                        reject_string = talloc_asprintf(mem_ctx, "Password must be at least %d characters long, and cannot match any of your %d previous passwords",
     
    149126                        break;
    150127                }
    151                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     128                return kpasswdd_make_error_reply(kdc, mem_ctx,
    152129                                                KRB5_KPASSWD_SOFTERROR,
    153130                                                reject_string,
     
    155132        }
    156133        if (!NT_STATUS_IS_OK(status)) {
    157                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     134                return kpasswdd_make_error_reply(kdc, mem_ctx,
    158135                                                 KRB5_KPASSWD_HARDERROR,
    159136                                                 talloc_asprintf(mem_ctx, "failed to set password: %s", nt_errstr(status)),
    160137                                                 error_blob);
    161                
     138
    162139        }
    163140        return kpasswdd_make_error_reply(kdc, mem_ctx, KRB5_KPASSWD_SUCCESS,
     
    166143}
    167144
    168 /* 
     145/*
    169146   A user password change
    170    
    171    Return true if there is a valid error packet (or sucess) formed in
     147
     148   Return true if there is a valid error packet (or success) formed in
    172149   the error_blob
    173150*/
    174151static bool kpasswdd_change_password(struct kdc_server *kdc,
    175                                      TALLOC_CTX *mem_ctx, 
     152                                     TALLOC_CTX *mem_ctx,
    176153                                     struct auth_session_info *session_info,
    177154                                     const DATA_BLOB *password,
     
    179156{
    180157        NTSTATUS status;
    181         enum samr_RejectReason reject_reason;
     158        enum samPwdChangeReason reject_reason;
    182159        struct samr_DomInfo1 *dominfo;
     160        struct samr_Password *oldLmHash, *oldNtHash;
    183161        struct ldb_context *samdb;
    184 
    185         samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, system_session(mem_ctx, kdc->task->lp_ctx));
     162        const char * const attrs[] = { "dBCSPwd", "unicodePwd", NULL };
     163        struct ldb_message **res;
     164        int ret;
     165
     166        /* Fetch the old hashes to get the old password in order to perform
     167         * the password change operation. Naturally it would be much better to
     168         * have a password hash from an authentication around but this doesn't
     169         * seem to be the case here. */
     170        ret = gendb_search(kdc->samdb, mem_ctx, NULL, &res, attrs,
     171                           "(&(objectClass=user)(sAMAccountName=%s))",
     172                           session_info->info->account_name);
     173        if (ret != 1) {
     174                return kpasswdd_make_error_reply(kdc, mem_ctx,
     175                                                KRB5_KPASSWD_ACCESSDENIED,
     176                                                "No such user when changing password",
     177                                                reply);
     178        }
     179
     180        status = samdb_result_passwords(mem_ctx, kdc->task->lp_ctx, res[0],
     181                                        &oldLmHash, &oldNtHash);
     182        if (!NT_STATUS_IS_OK(status)) {
     183                return kpasswdd_make_error_reply(kdc, mem_ctx,
     184                                                KRB5_KPASSWD_ACCESSDENIED,
     185                                                "Not permitted to change password",
     186                                                reply);
     187        }
     188
     189        /* Start a SAM with user privileges for the password change */
     190        samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx,
     191                              session_info, 0);
    186192        if (!samdb) {
    187                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     193                return kpasswdd_make_error_reply(kdc, mem_ctx,
    188194                                                KRB5_KPASSWD_HARDERROR,
    189195                                                "Failed to open samdb",
    190196                                                reply);
    191197        }
    192        
    193         DEBUG(3, ("Changing password of %s\\%s (%s)\n", 
    194                   session_info->server_info->domain_name,
    195                   session_info->server_info->account_name,
    196                   dom_sid_string(mem_ctx, session_info->security_token->user_sid)));
    197 
    198         /* User password change */
    199         status = samdb_set_password_sid(samdb, mem_ctx, 
    200                                         session_info->security_token->user_sid,
    201                                         password, NULL, NULL, 
    202                                         true, /* this is a user password change */
     198
     199        DEBUG(3, ("Changing password of %s\\%s (%s)\n",
     200                  session_info->info->domain_name,
     201                  session_info->info->account_name,
     202                  dom_sid_string(mem_ctx, &session_info->security_token->sids[PRIMARY_USER_SID_INDEX])));
     203
     204        /* Performs the password change */
     205        status = samdb_set_password_sid(samdb, mem_ctx,
     206                                        &session_info->security_token->sids[PRIMARY_USER_SID_INDEX],
     207                                        password, NULL, NULL,
     208                                        oldLmHash, oldNtHash, /* this is a user password change */
    203209                                        &reject_reason,
    204210                                        &dominfo);
    205         return kpasswd_make_pwchange_reply(kdc, mem_ctx, 
    206                                            status, 
     211        return kpasswd_make_pwchange_reply(kdc, mem_ctx,
     212                                           status,
    207213                                           reject_reason,
    208                                            dominfo, 
     214                                           dominfo,
    209215                                           reply);
    210216
     
    212218
    213219static bool kpasswd_process_request(struct kdc_server *kdc,
    214                                     TALLOC_CTX *mem_ctx, 
     220                                    TALLOC_CTX *mem_ctx,
    215221                                    struct gensec_security *gensec_security,
    216222                                    uint16_t version,
    217                                     DATA_BLOB *input, 
     223                                    DATA_BLOB *input,
    218224                                    DATA_BLOB *reply)
    219225{
     
    221227        size_t pw_len;
    222228
    223         if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security, 
     229        if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security,
    224230                                                 &session_info))) {
    225                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     231                return kpasswdd_make_error_reply(kdc, mem_ctx,
    226232                                                KRB5_KPASSWD_HARDERROR,
    227233                                                "gensec_session_info failed!",
     
    233239        {
    234240                DATA_BLOB password;
    235                 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(kdc->task->lp_ctx),
    236                                                CH_UTF8, CH_UTF16, 
    237                                                (const char *)input->data, 
     241                if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(kdc->task->lp_ctx),
     242                                               CH_UTF8, CH_UTF16,
     243                                               (const char *)input->data,
    238244                                               input->length,
    239245                                               (void **)&password.data, &pw_len, false)) {
     
    241247                }
    242248                password.length = pw_len;
    243        
    244                 return kpasswdd_change_password(kdc, mem_ctx, session_info, 
     249
     250                return kpasswdd_change_password(kdc, mem_ctx, session_info,
    245251                                                &password, reply);
    246                 break;
    247252        }
    248253        case KRB5_KPASSWD_VERS_SETPW:
    249254        {
    250255                NTSTATUS status;
    251                 enum samr_RejectReason reject_reason = SAMR_REJECT_OTHER;
     256                enum samPwdChangeReason reject_reason = SAM_PWD_CHANGE_NO_ERROR;
    252257                struct samr_DomInfo1 *dominfo = NULL;
    253258                struct ldb_context *samdb;
    254                 struct ldb_message *msg;
    255259                krb5_context context = kdc->smb_krb5_context->krb5_context;
    256260
     
    261265                char *set_password_on_princ;
    262266                struct ldb_dn *set_password_on_dn;
     267                bool service_principal_name = false;
    263268
    264269                size_t len;
    265270                int ret;
    266 
    267                 msg = ldb_msg_new(mem_ctx);
    268                 if (!msg) {
    269                         return false;
    270                 }
    271271
    272272                ret = decode_ChangePasswdDataMS(input->data, input->length,
    273273                                                &chpw, &len);
    274274                if (ret) {
    275                         return kpasswdd_make_error_reply(kdc, mem_ctx, 
     275                        return kpasswdd_make_error_reply(kdc, mem_ctx,
    276276                                                        KRB5_KPASSWD_MALFORMED,
    277277                                                        "failed to decode password change structure",
    278278                                                        reply);
    279279                }
    280                
    281                 if (!convert_string_talloc_convenience(mem_ctx, lp_iconv_convenience(kdc->task->lp_ctx),
    282                                                CH_UTF8, CH_UTF16, 
    283                                                (const char *)chpw.newpasswd.data, 
     280
     281                if (!convert_string_talloc_convenience(mem_ctx, lpcfg_iconv_convenience(kdc->task->lp_ctx),
     282                                               CH_UTF8, CH_UTF16,
     283                                               (const char *)chpw.newpasswd.data,
    284284                                               chpw.newpasswd.length,
    285285                                               (void **)&password.data, &pw_len, false)) {
     
    287287                        return false;
    288288                }
    289                
     289
    290290                password.length = pw_len;
    291        
    292                 if ((chpw.targname && !chpw.targrealm) 
     291
     292                if ((chpw.targname && !chpw.targrealm)
    293293                    || (!chpw.targname && chpw.targrealm)) {
    294                         return kpasswdd_make_error_reply(kdc, mem_ctx,
     294                        free_ChangePasswdDataMS(&chpw);
     295                        return kpasswdd_make_error_reply(kdc, mem_ctx,
    295296                                                        KRB5_KPASSWD_MALFORMED,
    296297                                                        "Realm and principal must be both present, or neither present",
     
    298299                }
    299300                if (chpw.targname && chpw.targrealm) {
    300 #ifdef SAMBA4_INTERNAL_HEIMDAL
    301                         if (_krb5_principalname2krb5_principal(kdc->smb_krb5_context->krb5_context,
    302                                                                &principal, *chpw.targname,
    303                                                                *chpw.targrealm) != 0) {
     301                        ret = krb5_build_principal_ext(kdc->smb_krb5_context->krb5_context,
     302                                                       &principal,
     303                                                       strlen(*chpw.targrealm),
     304                                                       *chpw.targrealm, 0);
     305                        if (ret) {
    304306                                free_ChangePasswdDataMS(&chpw);
    305                                 return kpasswdd_make_error_reply(kdc, mem_ctx,
     307                                return kpasswdd_make_error_reply(kdc, mem_ctx,
     308                                                                KRB5_KPASSWD_MALFORMED,
     309                                                                "failed to get principal",
     310                                                                reply);
     311                        }
     312                        if (copy_PrincipalName(chpw.targname, &principal->name)) {
     313                                free_ChangePasswdDataMS(&chpw);
     314                                krb5_free_principal(context, principal);
     315                                return kpasswdd_make_error_reply(kdc, mem_ctx,
    306316                                                                KRB5_KPASSWD_MALFORMED,
    307317                                                                "failed to extract principal to set",
    308318                                                                reply);
    309                                
    310319                        }
    311 #else /* SAMBA4_INTERNAL_HEIMDAL */
    312                                 return kpasswdd_make_error_reply(kdc, mem_ctx,
    313                                                                 KRB5_KPASSWD_BAD_VERSION,
    314                                                                 "Operation Not Implemented",
    315                                                                 reply);
    316 #endif /* SAMBA4_INTERNAL_HEIMDAL */
    317320                } else {
    318321                        free_ChangePasswdDataMS(&chpw);
    319                         return kpasswdd_change_password(kdc, mem_ctx, session_info, 
     322                        return kpasswdd_change_password(kdc, mem_ctx, session_info,
    320323                                                        &password, reply);
    321324                }
    322325                free_ChangePasswdDataMS(&chpw);
    323326
    324                 if (krb5_unparse_name(context, principal, &set_password_on_princ) != 0) {
    325                         krb5_free_principal(context, principal);
    326                         return kpasswdd_make_error_reply(kdc, mem_ctx,
    327                                                         KRB5_KPASSWD_MALFORMED,
    328                                                         "krb5_unparse_name failed!",
    329                                                         reply);
    330                 }
    331                
     327                if (principal->name.name_string.len >= 2) {
     328                        service_principal_name = true;
     329
     330                        /* We use this, rather than 'no realm' flag,
     331                         * as we don't want to accept a password
     332                         * change on a principal from another realm */
     333
     334                        if (krb5_unparse_name_short(context, principal, &set_password_on_princ) != 0) {
     335                                krb5_free_principal(context, principal);
     336                                return kpasswdd_make_error_reply(kdc, mem_ctx,
     337                                                                 KRB5_KPASSWD_MALFORMED,
     338                                                                 "krb5_unparse_name failed!",
     339                                                                 reply);
     340                        }
     341                } else {
     342                        if (krb5_unparse_name(context, principal, &set_password_on_princ) != 0) {
     343                                krb5_free_principal(context, principal);
     344                                return kpasswdd_make_error_reply(kdc, mem_ctx,
     345                                                                 KRB5_KPASSWD_MALFORMED,
     346                                                                 "krb5_unparse_name failed!",
     347                                                                 reply);
     348                        }
     349                }
    332350                krb5_free_principal(context, principal);
    333                
    334                 samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, session_info);
     351
     352                samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, session_info, 0);
    335353                if (!samdb) {
    336                         return kpasswdd_make_error_reply(kdc, mem_ctx,
     354                        free(set_password_on_princ);
     355                        return kpasswdd_make_error_reply(kdc, mem_ctx,
    337356                                                         KRB5_KPASSWD_HARDERROR,
    338357                                                         "Unable to open database!",
     
    340359                }
    341360
    342                 DEBUG(3, ("%s\\%s (%s) is changing password of %s\n", 
    343                           session_info->server_info->domain_name,
    344                           session_info->server_info->account_name,
    345                           dom_sid_string(mem_ctx, session_info->security_token->user_sid),
     361                DEBUG(3, ("%s\\%s (%s) is changing password of %s\n",
     362                          session_info->info->domain_name,
     363                          session_info->info->account_name,
     364                          dom_sid_string(mem_ctx, &session_info->security_token->sids[PRIMARY_USER_SID_INDEX]),
    346365                          set_password_on_princ));
    347366                ret = ldb_transaction_start(samdb);
    348                 if (ret) {
     367                if (ret != LDB_SUCCESS) {
     368                        free(set_password_on_princ);
    349369                        status = NT_STATUS_TRANSACTION_ABORTED;
    350                         return kpasswd_make_pwchange_reply(kdc, mem_ctx, 
     370                        return kpasswd_make_pwchange_reply(kdc, mem_ctx,
    351371                                                           status,
    352                                                            SAMR_REJECT_OTHER,
    353                                                            NULL, 
     372                                                           SAM_PWD_CHANGE_NO_ERROR,
     373                                                           NULL,
    354374                                                           reply);
    355375                }
    356376
    357                 status = crack_user_principal_name(samdb, mem_ctx,
    358                                                    set_password_on_princ,
    359                                                    &set_password_on_dn, NULL);
     377                if (service_principal_name) {
     378                        status = crack_service_principal_name(samdb, mem_ctx,
     379                                                              set_password_on_princ,
     380                                                              &set_password_on_dn, NULL);
     381                } else {
     382                        status = crack_user_principal_name(samdb, mem_ctx,
     383                                                           set_password_on_princ,
     384                                                           &set_password_on_dn, NULL);
     385                }
    360386                free(set_password_on_princ);
    361387                if (!NT_STATUS_IS_OK(status)) {
    362388                        ldb_transaction_cancel(samdb);
    363                         return kpasswd_make_pwchange_reply(kdc, mem_ctx, 
     389                        return kpasswd_make_pwchange_reply(kdc, mem_ctx,
    364390                                                           status,
    365                                                            SAMR_REJECT_OTHER,
    366                                                            NULL, 
     391                                                           SAM_PWD_CHANGE_NO_ERROR,
     392                                                           NULL,
    367393                                                           reply);
    368                 }
    369 
    370                 msg = ldb_msg_new(mem_ctx);
    371                 if (msg == NULL) {
    372                         ldb_transaction_cancel(samdb);
    373                         status = NT_STATUS_NO_MEMORY;
    374                 } else {
    375                         msg->dn = ldb_dn_copy(msg, set_password_on_dn);
    376                         if (!msg->dn) {
    377                                 status = NT_STATUS_NO_MEMORY;
    378                         }
    379394                }
    380395
     
    383398                        status = samdb_set_password(samdb, mem_ctx,
    384399                                                    set_password_on_dn, NULL,
    385                                                     msg, &password, NULL, NULL,
    386                                                     false, /* this is not a user password change */
     400                                                    &password, NULL, NULL,
     401                                                    NULL, NULL, /* this is not a user password change */
    387402                                                    &reject_reason, &dominfo);
    388403                }
    389404
    390                 if (NT_STATUS_IS_OK(status)) {
    391                         /* modify the samdb record */
    392                         ret = samdb_replace(samdb, mem_ctx, msg);
    393                         if (ret != 0) {
    394                                 DEBUG(2,("Failed to modify record to set password on %s: %s\n",
    395                                          ldb_dn_get_linearized(msg->dn),
    396                                          ldb_errstring(samdb)));
    397                                 status = NT_STATUS_ACCESS_DENIED;
    398                         }
    399                 }
    400405                if (NT_STATUS_IS_OK(status)) {
    401406                        ret = ldb_transaction_commit(samdb);
    402                         if (ret != 0) {
     407                        if (ret != LDB_SUCCESS) {
    403408                                DEBUG(1,("Failed to commit transaction to set password on %s: %s\n",
    404                                          ldb_dn_get_linearized(msg->dn),
     409                                         ldb_dn_get_linearized(set_password_on_dn),
    405410                                         ldb_errstring(samdb)));
    406411                                status = NT_STATUS_TRANSACTION_ABORTED;
     
    409414                        ldb_transaction_cancel(samdb);
    410415                }
    411                 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 
     416                return kpasswd_make_pwchange_reply(kdc, mem_ctx,
    412417                                                   status,
    413                                                    reject_reason, 
    414                                                    dominfo, 
     418                                                   reject_reason,
     419                                                   dominfo,
    415420                                                   reply);
    416421        }
    417422        default:
    418                 return kpasswdd_make_error_reply(kdc, mem_ctx, 
     423                return kpasswdd_make_error_reply(kdc, mem_ctx,
    419424                                                 KRB5_KPASSWD_BAD_VERSION,
    420                                                  talloc_asprintf(mem_ctx, 
    421                                                                  "Protocol version %u not supported", 
     425                                                 talloc_asprintf(mem_ctx,
     426                                                                 "Protocol version %u not supported",
    422427                                                                 version),
    423428                                                 reply);
    424429        }
    425         return true;
    426430}
    427431
    428 bool kpasswdd_process(struct kdc_server *kdc,
    429                       TALLOC_CTX *mem_ctx,
    430                       DATA_BLOB *input,
    431                       DATA_BLOB *reply,
    432                       struct socket_address *peer_addr,
    433                       struct socket_address *my_addr,
    434                       int datagram_reply)
     432enum kdc_process_ret kpasswdd_process(struct kdc_server *kdc,
     433                                      TALLOC_CTX *mem_ctx,
     434                                      DATA_BLOB *input,
     435                                      DATA_BLOB *reply,
     436                                      struct tsocket_address *peer_addr,
     437                                      struct tsocket_address *my_addr,
     438                                      int datagram_reply)
    435439{
    436440        bool ret;
     
    452456
    453457        if (!tmp_ctx) {
    454                 return false;
     458                return KDC_PROCESS_FAILED;
     459        }
     460
     461        if (kdc->am_rodc) {
     462                talloc_free(tmp_ctx);
     463                return KDC_PROCESS_PROXY;
    455464        }
    456465
     
    459468        if (input->length <= header_len) {
    460469                talloc_free(tmp_ctx);
    461                 return false;
     470                return KDC_PROCESS_FAILED;
    462471        }
    463472
     
    465474        if (input->length != len) {
    466475                talloc_free(tmp_ctx);
    467                 return false;
     476                return KDC_PROCESS_FAILED;
    468477        }
    469478
     
    475484        if ((ap_req_len >= len) || (ap_req_len + header_len) >= len) {
    476485                talloc_free(tmp_ctx);
    477                 return false;
    478         }
    479        
     486                return KDC_PROCESS_FAILED;
     487        }
     488
    480489        krb_priv_len = len - ap_req_len;
    481490        ap_req = data_blob_const(&input->data[header_len], ap_req_len);
    482491        krb_priv_req = data_blob_const(&input->data[header_len + ap_req_len], krb_priv_len);
    483        
     492
    484493        server_credentials = cli_credentials_init(tmp_ctx);
    485494        if (!server_credentials) {
    486495                DEBUG(1, ("Failed to init server credentials\n"));
    487                 return false;
     496                talloc_free(tmp_ctx);
     497                return KDC_PROCESS_FAILED;
    488498        }
    489499
    490500        /* We want the credentials subsystem to use the krb5 context
    491          * we already have, rather than a new context */       
     501         * we already have, rather than a new context */
    492502        cli_credentials_set_krb5_context(server_credentials, kdc->smb_krb5_context);
    493503        cli_credentials_set_conf(server_credentials, kdc->task->lp_ctx);
    494504
    495         keytab_name = talloc_asprintf(server_credentials, "HDB:samba4&%p", kdc->hdb_samba4_context);
     505        keytab_name = talloc_asprintf(server_credentials, "HDB:samba4&%p", kdc->base_ctx);
    496506
    497507        cli_credentials_set_username(server_credentials, "kadmin/changepw", CRED_SPECIFIED);
    498         ret = cli_credentials_set_keytab_name(server_credentials, kdc->task->event_ctx, kdc->task->lp_ctx, keytab_name, CRED_SPECIFIED);
     508        ret = cli_credentials_set_keytab_name(server_credentials, kdc->task->lp_ctx, keytab_name, CRED_SPECIFIED);
    499509        if (ret != 0) {
    500                 ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx, 
     510                ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx,
    501511                                                       KRB5_KPASSWD_HARDERROR,
    502                                                        talloc_asprintf(mem_ctx,
    503                                                                        "Failed to obtain server credentials for kadmin/changepw: %s\n",
    504                                                                        nt_errstr(nt_status)),
     512                                                       talloc_asprintf(mem_ctx,
     513                                                                       "Failed to obtain server credentials for kadmin/changepw!"),
    505514                                                       &krb_priv_rep);
    506515                ap_rep.length = 0;
     
    511520                return ret;
    512521        }
    513        
     522
    514523        /* We don't strictly need to call this wrapper, and could call
    515524         * gensec_server_start directly, as we have no need for NTLM
    516525         * and we have a PAC, but this ensures that the wrapper can be
    517526         * safely extended for other helpful things in future */
    518         nt_status = samba_server_gensec_start(tmp_ctx, kdc->task->event_ctx, 
     527        nt_status = samba_server_gensec_start(tmp_ctx, kdc->task->event_ctx,
    519528                                              kdc->task->msg_ctx,
    520529                                              kdc->task->lp_ctx,
    521530                                              server_credentials,
    522                                               "kpasswd", 
     531                                              "kpasswd",
    523532                                              &gensec_security);
    524533        if (!NT_STATUS_IS_OK(nt_status)) {
    525534                talloc_free(tmp_ctx);
    526                 return false;
     535                return KDC_PROCESS_FAILED;
    527536        }
    528537
     
    535544         * complex code */
    536545
    537         nt_status = gensec_set_peer_addr(gensec_security, peer_addr);
     546        nt_status = gensec_set_local_address(gensec_security, peer_addr);
    538547        if (!NT_STATUS_IS_OK(nt_status)) {
    539548                talloc_free(tmp_ctx);
    540                 return false;
     549                return KDC_PROCESS_FAILED;
    541550        }
    542551#endif
    543552
    544         nt_status = gensec_set_my_addr(gensec_security, my_addr);
     553        nt_status = gensec_set_local_address(gensec_security, my_addr);
    545554        if (!NT_STATUS_IS_OK(nt_status)) {
    546555                talloc_free(tmp_ctx);
    547                 return false;
     556                return KDC_PROCESS_FAILED;
    548557        }
    549558
     
    554563        if (!NT_STATUS_IS_OK(nt_status)) {
    555564                talloc_free(tmp_ctx);
    556                 return false;
     565                return KDC_PROCESS_FAILED;
    557566        }
    558567
     
    560569        nt_status = gensec_update(gensec_security, tmp_ctx, ap_req, &ap_rep);
    561570        if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
    562                
    563                 ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx, 
     571
     572                ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx,
    564573                                                       KRB5_KPASSWD_HARDERROR,
    565                                                        talloc_asprintf(mem_ctx, 
    566                                                                        "gensec_update failed: %s", 
     574                                                       talloc_asprintf(mem_ctx,
     575                                                                       "gensec_update failed: %s",
    567576                                                                       nt_errstr(nt_status)),
    568577                                                       &krb_priv_rep);
     
    572581                }
    573582                talloc_free(tmp_ctx);
    574                 return ret;
     583                return KDC_PROCESS_FAILED;
    575584        }
    576585
     
    578587        nt_status = gensec_unwrap(gensec_security, tmp_ctx, &krb_priv_req, &kpasswd_req);
    579588        if (!NT_STATUS_IS_OK(nt_status)) {
    580                 ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx, 
     589                ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx,
    581590                                                       KRB5_KPASSWD_HARDERROR,
    582                                                        talloc_asprintf(mem_ctx, 
    583                                                                        "gensec_unwrap failed: %s", 
     591                                                       talloc_asprintf(mem_ctx,
     592                                                                       "gensec_unwrap failed: %s",
    584593                                                                       nt_errstr(nt_status)),
    585594                                                       &krb_priv_rep);
     
    589598                }
    590599                talloc_free(tmp_ctx);
    591                 return ret;
     600                return KDC_PROCESS_FAILED;
    592601        }
    593602
    594603        /* Figure out something to do with it (probably changing a password...) */
    595         ret = kpasswd_process_request(kdc, tmp_ctx, 
    596                                       gensec_security, 
    597                                       version, 
    598                                       &kpasswd_req, &kpasswd_rep); 
     604        ret = kpasswd_process_request(kdc, tmp_ctx,
     605                                      gensec_security,
     606                                      version,
     607                                      &kpasswd_req, &kpasswd_rep);
    599608        if (!ret) {
    600609                /* Argh! */
    601                 return false;
     610                talloc_free(tmp_ctx);
     611                return KDC_PROCESS_FAILED;
    602612        }
    603613
    604614        /* And wrap up the reply: This ensures that the error message
    605615         * or success can be verified by the client */
    606         nt_status = gensec_wrap(gensec_security, tmp_ctx, 
     616        nt_status = gensec_wrap(gensec_security, tmp_ctx,
    607617                                &kpasswd_rep, &krb_priv_rep);
    608618        if (!NT_STATUS_IS_OK(nt_status)) {
    609                 ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx, 
     619                ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx,
    610620                                                       KRB5_KPASSWD_HARDERROR,
    611                                                        talloc_asprintf(mem_ctx, 
    612                                                                        "gensec_wrap failed: %s", 
     621                                                       talloc_asprintf(mem_ctx,
     622                                                                       "gensec_wrap failed: %s",
    613623                                                                       nt_errstr(nt_status)),
    614624                                                       &krb_priv_rep);
     
    618628                }
    619629                talloc_free(tmp_ctx);
    620                 return ret;
    621         }
    622        
     630                return KDC_PROCESS_FAILED;
     631        }
     632
    623633reply:
    624634        *reply = data_blob_talloc(mem_ctx, NULL, krb_priv_rep.length + ap_rep.length + header_len);
    625635        if (!reply->data) {
    626                 return false;
     636                talloc_free(tmp_ctx);
     637                return KDC_PROCESS_FAILED;
    627638        }
    628639
     
    630641        RSSVAL(reply->data, 2, 1); /* This is a version 1 reply, MS change/set or otherwise */
    631642        RSSVAL(reply->data, 4, ap_rep.length);
    632         memcpy(reply->data + header_len, 
    633                ap_rep.data, 
     643        memcpy(reply->data + header_len,
     644               ap_rep.data,
    634645               ap_rep.length);
    635         memcpy(reply->data + header_len + ap_rep.length, 
    636                krb_priv_rep.data, 
     646        memcpy(reply->data + header_len + ap_rep.length,
     647               krb_priv_rep.data,
    637648               krb_priv_rep.length);
    638649
    639650        talloc_free(tmp_ctx);
    640         return ret;
     651        return KDC_PROCESS_OK;
    641652}
    642653
Note: See TracChangeset for help on using the changeset viewer.