Changeset 745 for trunk/server/source4/kdc/kpasswdd.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/kdc/kpasswdd.c
r414 r745 1 /* 1 /* 2 2 Unix SMB/CIFS implementation. 3 3 … … 11 11 the Free Software Foundation; either version 3 of the License, or 12 12 (at your option) any later version. 13 13 14 14 This program is distributed in the hope that it will be useful, 15 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 17 GNU General Public License for more details. 18 18 19 19 You should have received a copy of the GNU General Public License 20 20 along with this program. If not, see <http://www.gnu.org/licenses/>. … … 23 23 #include "includes.h" 24 24 #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"30 25 #include "auth/gensec/gensec.h" 31 26 #include "auth/credentials/credentials.h" 32 #include "auth/credentials/credentials_krb5.h"33 27 #include "auth/auth.h" 34 28 #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" 37 30 #include "libcli/security/security.h" 38 31 #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" 55 33 56 34 /* 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) 35 static 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) 62 40 { 63 41 char *error_string_utf8; 64 42 size_t len; 65 43 66 44 DEBUG(result_code ? 3 : 10, ("kpasswdd: %s\n", error_string)); 67 45 … … 80 58 81 59 /* 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) 60 static 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) 87 65 { 88 66 bool ret; … … 90 68 DATA_BLOB error_bytes; 91 69 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, 93 71 &error_bytes); 94 72 if (!ret) { … … 98 76 k5_error_bytes.length = error_bytes.length; 99 77 kret = krb5_mk_error(kdc->smb_krb5_context->krb5_context, 100 result_code, NULL, &k5_error_bytes, 78 result_code, NULL, &k5_error_bytes, 101 79 NULL, NULL, NULL, NULL, &k5_error_blob); 102 80 if (kret) { … … 111 89 } 112 90 113 static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc, 114 TALLOC_CTX *mem_ctx, 115 NTSTATUS status, 116 enum sam r_RejectReason reject_reason,91 static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc, 92 TALLOC_CTX *mem_ctx, 93 NTSTATUS status, 94 enum samPwdChangeReason reject_reason, 117 95 struct samr_DomInfo1 *dominfo, 118 DATA_BLOB *error_blob) 96 DATA_BLOB *error_blob) 119 97 { 120 98 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, 122 100 KRB5_KPASSWD_ACCESSDENIED, 123 101 "No such user when changing password", … … 125 103 } 126 104 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, 128 106 KRB5_KPASSWD_ACCESSDENIED, 129 107 "Not permitted to change password", … … 133 111 const char *reject_string; 134 112 switch (reject_reason) { 135 case SAM R_REJECT_TOO_SHORT:113 case SAM_PWD_CHANGE_PASSWORD_TOO_SHORT: 136 114 reject_string = talloc_asprintf(mem_ctx, "Password too short, password must be at least %d characters long", 137 115 dominfo->min_password_length); 138 116 break; 139 case SAM R_REJECT_COMPLEXITY:117 case SAM_PWD_CHANGE_NOT_COMPLEX: 140 118 reject_string = "Password does not meet complexity requirements"; 141 119 break; 142 case SAM R_REJECT_IN_HISTORY:120 case SAM_PWD_CHANGE_PWD_IN_HISTORY: 143 121 reject_string = "Password is already in password history"; 144 122 break; 145 case SAMR_REJECT_OTHER:146 123 default: 147 124 reject_string = talloc_asprintf(mem_ctx, "Password must be at least %d characters long, and cannot match any of your %d previous passwords", … … 149 126 break; 150 127 } 151 return kpasswdd_make_error_reply(kdc, mem_ctx, 128 return kpasswdd_make_error_reply(kdc, mem_ctx, 152 129 KRB5_KPASSWD_SOFTERROR, 153 130 reject_string, … … 155 132 } 156 133 if (!NT_STATUS_IS_OK(status)) { 157 return kpasswdd_make_error_reply(kdc, mem_ctx, 134 return kpasswdd_make_error_reply(kdc, mem_ctx, 158 135 KRB5_KPASSWD_HARDERROR, 159 136 talloc_asprintf(mem_ctx, "failed to set password: %s", nt_errstr(status)), 160 137 error_blob); 161 138 162 139 } 163 140 return kpasswdd_make_error_reply(kdc, mem_ctx, KRB5_KPASSWD_SUCCESS, … … 166 143 } 167 144 168 /* 145 /* 169 146 A user password change 170 171 Return true if there is a valid error packet (or suc ess) formed in147 148 Return true if there is a valid error packet (or success) formed in 172 149 the error_blob 173 150 */ 174 151 static bool kpasswdd_change_password(struct kdc_server *kdc, 175 TALLOC_CTX *mem_ctx, 152 TALLOC_CTX *mem_ctx, 176 153 struct auth_session_info *session_info, 177 154 const DATA_BLOB *password, … … 179 156 { 180 157 NTSTATUS status; 181 enum sam r_RejectReason reject_reason;158 enum samPwdChangeReason reject_reason; 182 159 struct samr_DomInfo1 *dominfo; 160 struct samr_Password *oldLmHash, *oldNtHash; 183 161 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); 186 192 if (!samdb) { 187 return kpasswdd_make_error_reply(kdc, mem_ctx, 193 return kpasswdd_make_error_reply(kdc, mem_ctx, 188 194 KRB5_KPASSWD_HARDERROR, 189 195 "Failed to open samdb", 190 196 reply); 191 197 } 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 /* Userpassword 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 */ 203 209 &reject_reason, 204 210 &dominfo); 205 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 206 status, 211 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 212 status, 207 213 reject_reason, 208 dominfo, 214 dominfo, 209 215 reply); 210 216 … … 212 218 213 219 static bool kpasswd_process_request(struct kdc_server *kdc, 214 TALLOC_CTX *mem_ctx, 220 TALLOC_CTX *mem_ctx, 215 221 struct gensec_security *gensec_security, 216 222 uint16_t version, 217 DATA_BLOB *input, 223 DATA_BLOB *input, 218 224 DATA_BLOB *reply) 219 225 { … … 221 227 size_t pw_len; 222 228 223 if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security, 229 if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security, 224 230 &session_info))) { 225 return kpasswdd_make_error_reply(kdc, mem_ctx, 231 return kpasswdd_make_error_reply(kdc, mem_ctx, 226 232 KRB5_KPASSWD_HARDERROR, 227 233 "gensec_session_info failed!", … … 233 239 { 234 240 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, 238 244 input->length, 239 245 (void **)&password.data, &pw_len, false)) { … … 241 247 } 242 248 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, 245 251 &password, reply); 246 break;247 252 } 248 253 case KRB5_KPASSWD_VERS_SETPW: 249 254 { 250 255 NTSTATUS status; 251 enum sam r_RejectReason reject_reason = SAMR_REJECT_OTHER;256 enum samPwdChangeReason reject_reason = SAM_PWD_CHANGE_NO_ERROR; 252 257 struct samr_DomInfo1 *dominfo = NULL; 253 258 struct ldb_context *samdb; 254 struct ldb_message *msg;255 259 krb5_context context = kdc->smb_krb5_context->krb5_context; 256 260 … … 261 265 char *set_password_on_princ; 262 266 struct ldb_dn *set_password_on_dn; 267 bool service_principal_name = false; 263 268 264 269 size_t len; 265 270 int ret; 266 267 msg = ldb_msg_new(mem_ctx);268 if (!msg) {269 return false;270 }271 271 272 272 ret = decode_ChangePasswdDataMS(input->data, input->length, 273 273 &chpw, &len); 274 274 if (ret) { 275 return kpasswdd_make_error_reply(kdc, mem_ctx, 275 return kpasswdd_make_error_reply(kdc, mem_ctx, 276 276 KRB5_KPASSWD_MALFORMED, 277 277 "failed to decode password change structure", 278 278 reply); 279 279 } 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, 284 284 chpw.newpasswd.length, 285 285 (void **)&password.data, &pw_len, false)) { … … 287 287 return false; 288 288 } 289 289 290 290 password.length = pw_len; 291 292 if ((chpw.targname && !chpw.targrealm) 291 292 if ((chpw.targname && !chpw.targrealm) 293 293 || (!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, 295 296 KRB5_KPASSWD_MALFORMED, 296 297 "Realm and principal must be both present, or neither present", … … 298 299 } 299 300 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) { 304 306 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, 306 316 KRB5_KPASSWD_MALFORMED, 307 317 "failed to extract principal to set", 308 318 reply); 309 310 319 } 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 */317 320 } else { 318 321 free_ChangePasswdDataMS(&chpw); 319 return kpasswdd_change_password(kdc, mem_ctx, session_info, 322 return kpasswdd_change_password(kdc, mem_ctx, session_info, 320 323 &password, reply); 321 324 } 322 325 free_ChangePasswdDataMS(&chpw); 323 326 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 } 332 350 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); 335 353 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, 337 356 KRB5_KPASSWD_HARDERROR, 338 357 "Unable to open database!", … … 340 359 } 341 360 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]), 346 365 set_password_on_princ)); 347 366 ret = ldb_transaction_start(samdb); 348 if (ret) { 367 if (ret != LDB_SUCCESS) { 368 free(set_password_on_princ); 349 369 status = NT_STATUS_TRANSACTION_ABORTED; 350 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 370 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 351 371 status, 352 SAM R_REJECT_OTHER,353 NULL, 372 SAM_PWD_CHANGE_NO_ERROR, 373 NULL, 354 374 reply); 355 375 } 356 376 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 } 360 386 free(set_password_on_princ); 361 387 if (!NT_STATUS_IS_OK(status)) { 362 388 ldb_transaction_cancel(samdb); 363 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 389 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 364 390 status, 365 SAM R_REJECT_OTHER,366 NULL, 391 SAM_PWD_CHANGE_NO_ERROR, 392 NULL, 367 393 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 }379 394 } 380 395 … … 383 398 status = samdb_set_password(samdb, mem_ctx, 384 399 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 */ 387 402 &reject_reason, &dominfo); 388 403 } 389 404 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 }400 405 if (NT_STATUS_IS_OK(status)) { 401 406 ret = ldb_transaction_commit(samdb); 402 if (ret != 0) {407 if (ret != LDB_SUCCESS) { 403 408 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), 405 410 ldb_errstring(samdb))); 406 411 status = NT_STATUS_TRANSACTION_ABORTED; … … 409 414 ldb_transaction_cancel(samdb); 410 415 } 411 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 416 return kpasswd_make_pwchange_reply(kdc, mem_ctx, 412 417 status, 413 reject_reason, 414 dominfo, 418 reject_reason, 419 dominfo, 415 420 reply); 416 421 } 417 422 default: 418 return kpasswdd_make_error_reply(kdc, mem_ctx, 423 return kpasswdd_make_error_reply(kdc, mem_ctx, 419 424 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", 422 427 version), 423 428 reply); 424 429 } 425 return true;426 430 } 427 431 428 boolkpasswdd_process(struct kdc_server *kdc,429 TALLOC_CTX *mem_ctx,430 DATA_BLOB *input,431 DATA_BLOB *reply,432 structsocket_address *peer_addr,433 structsocket_address *my_addr,434 int datagram_reply)432 enum 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) 435 439 { 436 440 bool ret; … … 452 456 453 457 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; 455 464 } 456 465 … … 459 468 if (input->length <= header_len) { 460 469 talloc_free(tmp_ctx); 461 return false;470 return KDC_PROCESS_FAILED; 462 471 } 463 472 … … 465 474 if (input->length != len) { 466 475 talloc_free(tmp_ctx); 467 return false;476 return KDC_PROCESS_FAILED; 468 477 } 469 478 … … 475 484 if ((ap_req_len >= len) || (ap_req_len + header_len) >= len) { 476 485 talloc_free(tmp_ctx); 477 return false;478 } 479 486 return KDC_PROCESS_FAILED; 487 } 488 480 489 krb_priv_len = len - ap_req_len; 481 490 ap_req = data_blob_const(&input->data[header_len], ap_req_len); 482 491 krb_priv_req = data_blob_const(&input->data[header_len + ap_req_len], krb_priv_len); 483 492 484 493 server_credentials = cli_credentials_init(tmp_ctx); 485 494 if (!server_credentials) { 486 495 DEBUG(1, ("Failed to init server credentials\n")); 487 return false; 496 talloc_free(tmp_ctx); 497 return KDC_PROCESS_FAILED; 488 498 } 489 499 490 500 /* 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 */ 492 502 cli_credentials_set_krb5_context(server_credentials, kdc->smb_krb5_context); 493 503 cli_credentials_set_conf(server_credentials, kdc->task->lp_ctx); 494 504 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); 496 506 497 507 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); 499 509 if (ret != 0) { 500 ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx, 510 ret = kpasswdd_make_unauth_error_reply(kdc, mem_ctx, 501 511 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!"), 505 514 &krb_priv_rep); 506 515 ap_rep.length = 0; … … 511 520 return ret; 512 521 } 513 522 514 523 /* We don't strictly need to call this wrapper, and could call 515 524 * gensec_server_start directly, as we have no need for NTLM 516 525 * and we have a PAC, but this ensures that the wrapper can be 517 526 * 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, 519 528 kdc->task->msg_ctx, 520 529 kdc->task->lp_ctx, 521 530 server_credentials, 522 "kpasswd", 531 "kpasswd", 523 532 &gensec_security); 524 533 if (!NT_STATUS_IS_OK(nt_status)) { 525 534 talloc_free(tmp_ctx); 526 return false;535 return KDC_PROCESS_FAILED; 527 536 } 528 537 … … 535 544 * complex code */ 536 545 537 nt_status = gensec_set_ peer_addr(gensec_security, peer_addr);546 nt_status = gensec_set_local_address(gensec_security, peer_addr); 538 547 if (!NT_STATUS_IS_OK(nt_status)) { 539 548 talloc_free(tmp_ctx); 540 return false;549 return KDC_PROCESS_FAILED; 541 550 } 542 551 #endif 543 552 544 nt_status = gensec_set_ my_addr(gensec_security, my_addr);553 nt_status = gensec_set_local_address(gensec_security, my_addr); 545 554 if (!NT_STATUS_IS_OK(nt_status)) { 546 555 talloc_free(tmp_ctx); 547 return false;556 return KDC_PROCESS_FAILED; 548 557 } 549 558 … … 554 563 if (!NT_STATUS_IS_OK(nt_status)) { 555 564 talloc_free(tmp_ctx); 556 return false;565 return KDC_PROCESS_FAILED; 557 566 } 558 567 … … 560 569 nt_status = gensec_update(gensec_security, tmp_ctx, ap_req, &ap_rep); 561 570 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, 564 573 KRB5_KPASSWD_HARDERROR, 565 talloc_asprintf(mem_ctx, 566 "gensec_update failed: %s", 574 talloc_asprintf(mem_ctx, 575 "gensec_update failed: %s", 567 576 nt_errstr(nt_status)), 568 577 &krb_priv_rep); … … 572 581 } 573 582 talloc_free(tmp_ctx); 574 return ret;583 return KDC_PROCESS_FAILED; 575 584 } 576 585 … … 578 587 nt_status = gensec_unwrap(gensec_security, tmp_ctx, &krb_priv_req, &kpasswd_req); 579 588 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, 581 590 KRB5_KPASSWD_HARDERROR, 582 talloc_asprintf(mem_ctx, 583 "gensec_unwrap failed: %s", 591 talloc_asprintf(mem_ctx, 592 "gensec_unwrap failed: %s", 584 593 nt_errstr(nt_status)), 585 594 &krb_priv_rep); … … 589 598 } 590 599 talloc_free(tmp_ctx); 591 return ret;600 return KDC_PROCESS_FAILED; 592 601 } 593 602 594 603 /* 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); 599 608 if (!ret) { 600 609 /* Argh! */ 601 return false; 610 talloc_free(tmp_ctx); 611 return KDC_PROCESS_FAILED; 602 612 } 603 613 604 614 /* And wrap up the reply: This ensures that the error message 605 615 * 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, 607 617 &kpasswd_rep, &krb_priv_rep); 608 618 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, 610 620 KRB5_KPASSWD_HARDERROR, 611 talloc_asprintf(mem_ctx, 612 "gensec_wrap failed: %s", 621 talloc_asprintf(mem_ctx, 622 "gensec_wrap failed: %s", 613 623 nt_errstr(nt_status)), 614 624 &krb_priv_rep); … … 618 628 } 619 629 talloc_free(tmp_ctx); 620 return ret;621 } 622 630 return KDC_PROCESS_FAILED; 631 } 632 623 633 reply: 624 634 *reply = data_blob_talloc(mem_ctx, NULL, krb_priv_rep.length + ap_rep.length + header_len); 625 635 if (!reply->data) { 626 return false; 636 talloc_free(tmp_ctx); 637 return KDC_PROCESS_FAILED; 627 638 } 628 639 … … 630 641 RSSVAL(reply->data, 2, 1); /* This is a version 1 reply, MS change/set or otherwise */ 631 642 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, 634 645 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, 637 648 krb_priv_rep.length); 638 649 639 650 talloc_free(tmp_ctx); 640 return ret;651 return KDC_PROCESS_OK; 641 652 } 642 653
Note:
See TracChangeset
for help on using the changeset viewer.