?? xauth.c
字號:
if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) { return STF_INTERNAL_ERROR; } } START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_ATTR); /* ATTR out */ { struct isakmp_mode_attr attrh; struct isakmp_attribute attr; pb_stream strattr; attrh.isama_np = ISAKMP_NEXT_NONE; attrh.isama_type = ISAKMP_CFG_REQUEST; attrh.isama_identifier = 0; if(!out_struct(&attrh, &isakmp_attr_desc, &rbody, &strattr)) return STF_INTERNAL_ERROR; /* ISAKMP attr out (name) */ attr.isaat_af_type = XAUTH_USER_NAME; attr.isaat_lv = 0; out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, NULL); /* ISAKMP attr out (password) */ attr.isaat_af_type = XAUTH_USER_PASSWORD; attr.isaat_lv = 0; out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, NULL); close_message(&strattr); } xauth_mode_cfg_hash(r_hashval,r_hash_start,rbody.cur,st); close_message(&rbody); close_output_pbs(&reply); init_phase2_iv(st, &st->st_msgid); encrypt_message(&rbody, st); clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply) , "XAUTH: req"); /* Transmit */ send_packet(st, "XAUTH: req"); /* RETRANSMIT if Main, SA_REPLACE if Aggressive */ if(st->st_event->ev_type != EVENT_RETRANSMIT) { delete_event(st); event_schedule(EVENT_RETRANSMIT,EVENT_RETRANSMIT_DELAY_0 * 3,st); } return STF_OK;}/** Send modecfg IP address request (IP4 address) * @param st State * @return stf_status */stf_status modecfg_send_request(struct state *st){ pb_stream reply; pb_stream rbody; char buf[256]; u_char *r_hash_start,*r_hashval; /* set up reply */ init_pbs(&reply, buf, sizeof(buf), "xauth_buf"); openswan_log("modecfg: Sending IP request (MODECFG_I1)"); /* this is the beginning of a new exchange */ st->st_msgid = generate_msgid(st); st->st_state = STATE_MODE_CFG_I1; /* HDR out */ { struct isakmp_hdr hdr; zero(&hdr); /* default to 0 */ hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; hdr.isa_np = ISAKMP_NEXT_HASH; hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG; hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); hdr.isa_msgid = st->st_msgid; if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) { return STF_INTERNAL_ERROR; } } START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_ATTR); /* ATTR out */ { struct isakmp_mode_attr attrh; struct isakmp_attribute attr; pb_stream strattr; attrh.isama_np = ISAKMP_NEXT_NONE; attrh.isama_type = ISAKMP_CFG_REQUEST; attrh.isama_identifier = 0; if(!out_struct(&attrh, &isakmp_attr_desc, &rbody, &strattr)) return STF_INTERNAL_ERROR; /* ISAKMP attr out (ipv4) */ attr.isaat_af_type = INTERNAL_IP4_ADDRESS; attr.isaat_lv = 0; out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, NULL); /* ISAKMP attr out (netmask) */ attr.isaat_af_type = INTERNAL_IP4_NETMASK; attr.isaat_lv = 0; out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, NULL); close_message(&strattr); } xauth_mode_cfg_hash(r_hashval,r_hash_start,rbody.cur,st); close_message(&rbody); close_output_pbs(&reply); init_phase2_iv(st, &st->st_msgid); encrypt_message(&rbody, st); clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply) , "modecfg: req"); /* Transmit */ send_packet(st, "modecfg: req"); /* RETRANSMIT if Main, SA_REPLACE if Aggressive */ if(st->st_event->ev_type != EVENT_RETRANSMIT) { delete_event(st); event_schedule(EVENT_RETRANSMIT,EVENT_RETRANSMIT_DELAY_0 * 3,st); } st->hidden_variables.st_modecfg_started = TRUE; return STF_OK;}/** Send XAUTH status to client * * @param st State * @param status Status code * @return stf_status */stf_status xauth_send_status(struct state *st, int status){ pb_stream reply; pb_stream rbody; char buf[256]; u_char *r_hash_start,*r_hashval; /* set up reply */ init_pbs(&reply, buf, sizeof(buf), "xauth_buf"); /* pick a new message id */ st->st_msgid = generate_msgid(st); /* HDR out */ { struct isakmp_hdr hdr; zero(&hdr); /* default to 0 */ hdr.isa_version = ISAKMP_MAJOR_VERSION << ISA_MAJ_SHIFT | ISAKMP_MINOR_VERSION; hdr.isa_np = ISAKMP_NEXT_HASH; hdr.isa_xchg = ISAKMP_XCHG_MODE_CFG; hdr.isa_flags = ISAKMP_FLAG_ENCRYPTION; memcpy(hdr.isa_icookie, st->st_icookie, COOKIE_SIZE); memcpy(hdr.isa_rcookie, st->st_rcookie, COOKIE_SIZE); hdr.isa_msgid = st->st_msgid; if (!out_struct(&hdr, &isakmp_hdr_desc, &reply, &rbody)) { return STF_INTERNAL_ERROR; } } START_HASH_PAYLOAD(rbody, ISAKMP_NEXT_ATTR); /* ATTR out */ { struct isakmp_mode_attr attrh; struct isakmp_attribute attr; pb_stream strattr; attrh.isama_np = ISAKMP_NEXT_NONE; attrh.isama_type = ISAKMP_CFG_SET; attrh.isama_identifier = 0; if(!out_struct(&attrh, &isakmp_attr_desc, &rbody, &strattr)) return STF_INTERNAL_ERROR; /* ISAKMP attr out (status) */#if 1 attr.isaat_af_type = XAUTH_STATUS | ISAKMP_ATTR_AF_TV; attr.isaat_lv = status; out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, NULL);#else attr.isaat_af_type = XAUTH_STATUS | ISAKMP_ATTR_AF_TLV; out_struct(&attr, &isakmp_xauth_attribute_desc, &strattr, &val); status = htonl(status); out_raw(&status,4,&val,"Status"); close_output_pbs(&val);#endif close_message(&strattr); } xauth_mode_cfg_hash(r_hashval,r_hash_start,rbody.cur,st); close_message(&rbody); close_output_pbs(&reply); init_phase2_iv(st, &st->st_msgid); encrypt_message(&rbody, st); /* free previous transmit packet */ freeanychunk(st->st_tpacket); clonetochunk(st->st_tpacket, reply.start, pbs_offset(&reply) , "XAUTH: status"); /* Set up a retransmission event, half a minute henceforth */ /* Schedule retransmit before sending, to avoid race with master thread */ delete_event(st); event_schedule(EVENT_RETRANSMIT, EVENT_RETRANSMIT_DELAY_0, st); /* Transmit */ send_packet(st, "XAUTH: status"); st->st_state = STATE_XAUTH_R1; return STF_OK;}#ifdef XAUTH_USEPAM/** XAUTH PAM conversation * * @param num_msg Int. * @param msgm Pam Message Struct * @param response Where PAM will put the results * @param appdata_ptr Pointer to data struct (as we are using threads) * @return int Return Code */staticint xauth_pam_conv(int num_msg, const struct pam_message **msgm, struct pam_response **response, void *appdata_ptr){ struct thread_arg *arg = appdata_ptr; int count=0; struct pam_response *reply; if (num_msg <= 0) return PAM_CONV_ERR; reply = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response)); if (reply == NULL) { return PAM_CONV_ERR; } for (count=0; count < num_msg; ++count) { char *string=NULL; switch (msgm[count]->msg_style) { case PAM_PROMPT_ECHO_OFF: string = malloc(arg->password.len+1); strcpy(string,arg->password.ptr); break; case PAM_PROMPT_ECHO_ON: string = malloc(arg->name.len+1); strcpy(string,arg->name.ptr); break; } if (string) { /* must add to reply array */ /* add string to list of responses */ reply[count].resp_retcode = 0; reply[count].resp = string; string = NULL; } } *response = reply; reply = NULL; return PAM_SUCCESS;}#endif#ifdef XAUTH_USEPAM/** Do authentication via PAM (Plugable Authentication Modules) * * We open a PAM session via pam_start, and try to authenticate the user * * @return int Return Code */staticint do_pam_authentication(void *varg){ struct thread_arg *arg = varg; pam_handle_t *pamh=NULL; int retval; conv.appdata_ptr = varg; retval = pam_start("pluto", arg->name.ptr, &conv, &pamh); /* Two factor authentication - Check that the user is valid, and then check if they are permitted access */ if (retval == PAM_SUCCESS) retval = pam_authenticate(pamh, PAM_SILENT); /* is user really user? */ if (retval == PAM_SUCCESS) retval = pam_acct_mgmt(pamh, 0); /* permitted access? */ pam_end(pamh, PAM_SUCCESS); if(retval == PAM_SUCCESS) return TRUE; else return FALSE;}#else /* XAUTH_USEPAM *//** Do authentication via /etc/ipsec.d/passwd file using MD5 passwords * * password file structure does not compensate for * extra garbage so don't leave any! we do allows for #'s * as first char for comments just because I hate conf * files like .htaccess that don't support it * * /etc/ipsec.d/passwd * username:md5sum:connectioname\n * * can be made with, htpasswd: * * htpasswd -c -m -b /etc/ipsec.d/passwd road roadpass * * @return int Return Code */staticint do_md5_authentication(void *varg){ struct thread_arg *arg = varg; int len; char szline[1024]; /* more than enough */ FILE *fp; char *szuser; char *szpass; char *szconnid; char *sztemp; int loc = 0; size_t pwlen = strlen(ipsec_dir) + sizeof("/passwd") + 1; verify_path_space(&pwdfile, pwlen, "xauth passwd file path"); snprintf(pwdfile.path, pwdfile.path_space, "%s/passwd", ipsec_dir); fp = fopen(pwdfile.path, "r"); if( fp == (FILE *)0) { /* unable to open the password file */ openswan_log("XAUTH: unable to open password file (%s) for verification", pwdfile.path); return FALSE; } openswan_log("XAUTH: password file (%s) open.", pwdfile.path); /** simple stuff read in a line then go through positioning * szuser ,szpass and szconnid at the begining of each of the * memory locations of our real data and replace the ':' with '\0' */ while( fgets( szline, sizeof(szline), fp) != (char *)0) { len = strlen( szline ); loc = 0; /* reset our index */ if(szline[0] == '#') /* comment line move on */ continue; /* get userid */ sztemp = strchr(szline, ':'); if (sztemp == (char *)0 ) continue; /* we found no tokens bad line so just skip it */ *sztemp++ = '\0'; /* put a null where the ':' was */ szuser = &szline[loc]; /* szline now contains our null terminated data */ loc+=strlen(szuser)+1; /* move past null into next section */ /* get password */ sztemp = strchr(&szline[loc], ':'); if (sztemp == (char *)0 ) continue; /* we found no tokens bad line so just skip it */ *sztemp++ = '\0'; /* put a null where the ':' was */ szpass = &szline[loc]; /* szline now contains our null terminated data */ loc+=strlen(szpass)+1; /* move past null into next section */ /* get connection id */ sztemp = strchr(&szline[loc], '\n'); /* last \n */ if (sztemp == (char *)0 ) continue; /* we found no tokens bad line so just skip it */ *sztemp++ = '\0'; /* put a null where the ':' was */ szconnid = &szline[loc]; /* szline now contains our null terminated data */ /* it is possible that szconnid will be null so don't bother * checking it. If it is null then this is to say it applies * to all connection classes */ DBG(DBG_CONTROL, DBG_log("XAUTH: found user(%s/%s) pass(%s) connid(%s/%s)" , szuser, arg->name.ptr , szpass, szconnid, arg->connname.ptr)); if ( strcasecmp(szconnid, arg->connname.ptr) == 0 && strcmp( szuser, arg->name.ptr ) == 0 ) /* user correct ?*/ { char *cp; cp = crypt( arg->password.ptr, szpass); if(DBGP(DBG_CRYPT)) { DBG_log("XAUTH: checking user(%s:%s) pass %s vs %s" , szuser, szconnid, cp, szpass); } else { openswan_log("XAUTH: checking user(%s:%s) " , szuser, szconnid); } /* Ok then now password check */ if ( strcmp(cp, szpass ) == 0 ) { /* we have a winner */ fclose( fp ); return TRUE; } openswan_log("XAUTH: nope"); } } fclose( fp ); return FALSE;}#endif/** Main authentication routine will then call the actual compiled in * method to verify the user/password */static void * do_authentication(void *varg){ struct thread_arg *arg = varg; struct state *st = arg->st; int results=FALSE; openswan_log("XAUTH: User %s: Attempting to login" , arg->name.ptr); #ifdef XAUTH_USEPAM openswan_log("XAUTH: pam authentication being called to authenticate user %s",arg->name.ptr); results=do_pam_authentication(varg);#else openswan_log("XAUTH: md5 authentication being called to authenticate user %s",arg->name.ptr); results=do_md5_authentication(varg);#endif if(results) { openswan_log("XAUTH: User %s: Authentication Successful", arg->name.ptr); xauth_send_status(st,1); if(st->quirks.xauth_ack_msgid) { st->st_msgid = 0; } } else { /** Login attempt failed, display error, send XAUTH status to client * and reset state to XAUTH_R0 */ openswan_log("XAUTH: User %s: Authentication Failed: Incorrect Username or Password", arg->name.ptr); xauth_send_status(st,0); st->st_state = STATE_XAUTH_R0; } freeanychunk(arg->password); freeanychunk(arg->name); freeanychunk(arg->connname); pfree(varg); return NULL;}/** Launch an authenication prompt * * @param st State Structure * @param name Usernamd * @param password password * @param connname conn name, from ipsec.conf * @return int Return Code - always 0. */int xauth_launch_authent(struct state *st , chunk_t name , chunk_t password , chunk_t connname){#ifdef HAVE_THREADS pthread_attr_t pattr; pthread_t tid;#endif struct thread_arg *arg; arg = alloc_thing(struct thread_arg,"ThreadArg"); arg->st = st; arg->password = password; arg->name = name; arg->connname = connname;#ifdef HAVE_THREADS pthread_attr_init(&pattr); pthread_attr_setdetachstate(&pattr,PTHREAD_CREATE_DETACHED); pthread_create(&tid,&pattr,do_authentication, (void*) arg); pthread_attr_destroy(&pattr);#else do_authentication(arg);#endif return 0;}/** STATE_XAUTH_R0: * First REQUEST sent, expect for REPLY * HDR*, HASH, ATTR(REPLY,PASSWORD) --> HDR*, HASH, ATTR(STATUS) * * @param md Message Digest * @return stf_status */stf_statusxauth_inR0(struct msg_digest *md){ pb_stream *attrs = &md->chain[ISAKMP_NEXT_ATTR]->pbs; struct state *const st = md->st; chunk_t name, password, connname; bool gotname, gotpassword; gotname = gotpassword = FALSE; CHECK_QUICK_HASH(md,xauth_mode_cfg_hash(hash_val,hash_pbs->roof, md->message_pbs.roof, st) , "XAUTH-HASH", "XAUTH R0"); { struct isakmp_attribute attr; pb_stream strattr; if (md->chain[ISAKMP_NEXT_ATTR]->payload.attribute.isama_type != ISAKMP_CFG_REPLY) { openswan_log("Expecting MODE_CFG_REPLY, got %s instead." , enum_name(&attr_msg_type_names, md->chain[ISAKMP_NEXT_ATTR]->payload.attribute.isama_type)); return STF_IGNORE; } while(pbs_left(attrs) > sizeof(struct isakmp_attribute))
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -