/* * @returns: the number of bytes sent, if succeeds * -1, if fails */ int _condorOutMsg::sendMsg(const int sock, const condor_sockaddr& who, _condorMsgID msgID, unsigned char * mac) { _condorPacket* tempPkt; int seqNo = 0, msgLen = 0, sent; int total = 0; unsigned char * md = mac; //char str[10000]; if(headPacket->empty()) // empty message return 0; while(headPacket != lastPacket) { tempPkt = headPacket; headPacket = headPacket->next; tempPkt->makeHeader(false, seqNo++, msgID, md); msgLen += tempPkt->length; sent = condor_sendto(sock, tempPkt->dataGram, tempPkt->length + SAFE_MSG_HEADER_SIZE, 0, who); if(sent != tempPkt->length + SAFE_MSG_HEADER_SIZE) { dprintf(D_ALWAYS, "sendMsg:sendto failed - errno: %d\n", errno); headPacket = tempPkt; clearMsg(); return -1; } //int i; //str[0] = 0; //for (i=0; i<tempPkt->length + SAFE_MSG_HEADER_SIZE; i++) { // sprintf(&str[strlen(str)], "%02x,", tempPkt->dataGram[i]); //} //dprintf(D_NETWORK, "--->packet [%d bytes]: %s\n", sent, str); dprintf( D_NETWORK, "SEND [%d] %s ", sent, sock_to_string(sock) ); dprintf( D_NETWORK|D_NOHEADER, "%s\n", who.to_sinful().Value()); total += sent; delete tempPkt; md = 0; } // headPacket = lastPacket if(seqNo == 0) { // a short message msgLen = lastPacket->length; lastPacket->makeHeader(true, 0, msgID, md); // Short messages are sent without initial "magic" header, // because we don't need to specify sequence number, // and presumably for backwards compatibility with ancient // versions of Condor. The crypto header may still // be there, since that is in the buffer starting at // the position pointed to by "data". sent = condor_sendto(sock, lastPacket->data, lastPacket->length, 0, who); if(sent != lastPacket->length) { dprintf( D_ALWAYS, "SafeMsg: sending small msg failed. errno: %d\n", errno ); headPacket->reset(); return -1; } //str[0] = 0; //for (i=0; i<lastPacket->length + SAFE_MSG_HEADER_SIZE; i++) { // sprintf(&str[strlen(str)], "%02x,", lastPacket->dataGram[i]); //} //dprintf(D_NETWORK, "--->packet [%d bytes]: %s\n", sent, str); dprintf( D_NETWORK, "SEND [%d] %s ", sent, sock_to_string(sock) ); dprintf( D_NETWORK|D_NOHEADER, "%s\n", who.to_sinful().Value()); total = sent; } else { lastPacket->makeHeader(true, seqNo, msgID, md); msgLen += lastPacket->length; sent = condor_sendto(sock, lastPacket->dataGram, lastPacket->length + SAFE_MSG_HEADER_SIZE, 0, who); if(sent != lastPacket->length + SAFE_MSG_HEADER_SIZE) { dprintf( D_ALWAYS, "SafeMsg: sending last packet failed. errno: %d\n", errno ); headPacket->reset(); return -1; } //str[0] = 0; //for (i=0; i<lastPacket->length + SAFE_MSG_HEADER_SIZE; i++) { // sprintf(&str[strlen(str)], "%02x,", lastPacket->dataGram[i]); //} //dprintf(D_NETWORK, "--->packet [%d bytes]: %s\n", sent, str); dprintf( D_NETWORK, "SEND [%d] %s ", sent, sock_to_string(sock) ); dprintf( D_NETWORK|D_NOHEADER, "%s\n", who.to_sinful().Value()); total += sent; } headPacket->reset(); noMsgSent++; if(noMsgSent == 1) avgMsgSize = msgLen; else avgMsgSize = ((noMsgSent - 1) * avgMsgSize + msgLen) / noMsgSent; return total; }
int IpVerify::Verify( DCpermission perm, const condor_sockaddr& addr, const char * user, MyString *allow_reason, MyString *deny_reason ) { perm_mask_t mask; in6_addr sin6_addr; const char *thehost; const char * who = user; MyString peer_description; // we build this up as we go along (DNS etc.) if( !did_init ) { Init(); } /* * Be Warned: careful about parameter "sin" being NULL. It could be, in * which case we should return FALSE (unless perm is ALLOW) * */ switch ( perm ) { case ALLOW: return USER_AUTH_SUCCESS; break; default: break; } sin6_addr = addr.to_ipv6_address(); mask = 0; // must initialize to zero because we logical-or bits into this if (who == NULL || *who == '\0') { who = TotallyWild; } if ( perm >= LAST_PERM || !PermTypeArray[perm] ) { EXCEPT("IpVerify::Verify: called with unknown permission %d\n",perm); } // see if a authorization hole has been dyamically punched (via // PunchHole) for this perm / user / IP // Note that the permission hierarchy is dealt with in // PunchHole(), by punching a hole for all implied levels. // Therefore, if there is a hole or an implied hole, we will // always find it here before we get into the subsequent code // which recursively calls Verify() to traverse the hierarchy. // This is important, because we do not want holes to find // there way into the authorization cache. // if ( PunchedHoleArray[perm] != NULL ) { HolePunchTable_t* hpt = PunchedHoleArray[perm]; MyString ip_str_buf = addr.to_ip_string(); const char* ip_str = ip_str_buf.Value(); MyString id_with_ip; MyString id; int count; if ( who != TotallyWild ) { id_with_ip.sprintf("%s/%s", who, ip_str); id = who; if ( hpt->lookup(id, count) != -1 ) { if( allow_reason ) { allow_reason->sprintf( "%s authorization has been made automatic for %s", PermString(perm), id.Value() ); } return USER_AUTH_SUCCESS; } if ( hpt->lookup(id_with_ip, count) != -1 ) { if( allow_reason ) { allow_reason->sprintf( "%s authorization has been made automatic for %s", PermString(perm), id_with_ip.Value() ); } return USER_AUTH_SUCCESS; } } id = ip_str; if ( hpt->lookup(id, count) != -1 ) { if( allow_reason ) { allow_reason->sprintf( "%s authorization has been made automatic for %s", PermString(perm), id.Value() ); } return USER_AUTH_SUCCESS; } } if ( PermTypeArray[perm]->behavior == USERVERIFY_ALLOW ) { // allow if no HOSTALLOW_* or HOSTDENY_* restrictions // specified. if( allow_reason ) { allow_reason->sprintf( "%s authorization policy allows access by anyone", PermString(perm)); } return USER_AUTH_SUCCESS; } if ( PermTypeArray[perm]->behavior == USERVERIFY_DENY ) { // deny if( deny_reason ) { deny_reason->sprintf( "%s authorization policy denies all access", PermString(perm)); } return USER_AUTH_FAILURE; } if( LookupCachedVerifyResult(perm,sin6_addr,who,mask) ) { if( deny_reason && (mask&deny_mask(perm)) ) { deny_reason->sprintf( "cached result for %s; see first case for the full reason", PermString(perm)); } else if( allow_reason && (mask&allow_mask(perm)) ) { allow_reason->sprintf( "cached result for %s; see first case for the full reason", PermString(perm)); } } else { mask = 0; // if the deny bit is already set, skip further DENY analysis perm_mask_t const deny_resolved = deny_mask(perm); // if the allow or deny bit is already set, // skip further ALLOW analysis perm_mask_t const allow_resolved = allow_mask(perm)|deny_mask(perm); // check for matching subnets in ip/mask style char ipstr[INET6_ADDRSTRLEN] = { 0, }; addr.to_ip_string(ipstr, INET6_ADDRSTRLEN); peer_description = addr.to_ip_string(); if ( !(mask&deny_resolved) && lookup_user_ip_deny(perm,who,ipstr)) { mask |= deny_mask(perm); if( deny_reason ) { deny_reason->sprintf( "%s authorization policy denies IP address %s", PermString(perm), addr.to_ip_string().Value() ); } } if ( !(mask&allow_resolved) && lookup_user_ip_allow(perm,who,ipstr)) { mask |= allow_mask(perm); if( allow_reason ) { allow_reason->sprintf( "%s authorization policy allows IP address %s", PermString(perm), addr.to_ip_string().Value() ); } } std::vector<MyString> hostnames; // now scan through hostname strings if( !(mask&allow_resolved) || !(mask&deny_resolved) ) { hostnames = get_hostname_with_alias(addr); } for (unsigned int i = 0; i < hostnames.size(); ++i) { thehost = hostnames[i].Value(); peer_description.append_to_list(thehost); if ( !(mask&deny_resolved) && lookup_user_host_deny(perm,who,thehost) ) { mask |= deny_mask(perm); if( deny_reason ) { deny_reason->sprintf( "%s authorization policy denies hostname %s", PermString(perm), thehost ); } } if ( !(mask&allow_resolved) && lookup_user_host_allow(perm,who,thehost) ) { mask |= allow_mask(perm); if( allow_reason ) { allow_reason->sprintf( "%s authorization policy allows hostname %s", PermString(perm), thehost ); } } } // if we found something via our hostname or subnet mactching, we now have // a mask, and we should add it into our table so we need not // do a gethostbyaddr() next time. if we still do not have a mask // (perhaps because this host doesn't appear in any list), create one // and then add to the table. // But first, check our parent permission levels in the // authorization heirarchy. // DAEMON and ADMINISTRATOR imply WRITE. // WRITE, NEGOTIATOR, and CONFIG_PERM imply READ. bool determined_by_parent = false; if ( mask == 0 ) { if ( PermTypeArray[perm]->behavior == USERVERIFY_ONLY_DENIES ) { dprintf(D_SECURITY,"IPVERIFY: %s at %s not matched to deny list, so allowing.\n",who, addr.to_sinful().Value()); if( allow_reason ) { allow_reason->sprintf( "%s authorization policy does not deny, so allowing", PermString(perm)); } mask |= allow_mask(perm); } else { DCpermissionHierarchy hierarchy( perm ); DCpermission const *parent_perms = hierarchy.getPermsIAmDirectlyImpliedBy(); bool parent_allowed = false; for( ; *parent_perms != LAST_PERM; parent_perms++ ) { if( Verify( *parent_perms, addr, user, allow_reason, NULL ) == USER_AUTH_SUCCESS ) { determined_by_parent = true; parent_allowed = true; dprintf(D_SECURITY,"IPVERIFY: allowing %s at %s for %s because %s is allowed\n",who, addr.to_sinful().Value(),PermString(perm),PermString(*parent_perms)); if( allow_reason ) { MyString tmp = *allow_reason; allow_reason->sprintf( "%s is implied by %s; %s", PermString(perm), PermString(*parent_perms), tmp.Value()); } break; } } if( parent_allowed ) { mask |= allow_mask(perm); } else { mask |= deny_mask(perm); if( !determined_by_parent && deny_reason ) { // We don't just allow anyone, and this request // did not match any of the entries we do allow. // In case the reason we didn't match is // because of a typo or a DNS problem, record // all the hostnames we searched for. deny_reason->sprintf( "%s authorization policy contains no matching " "ALLOW entry for this request" "; identifiers used for this host: %s, hostname size = %lu, " "original ip address = %s", PermString(perm), peer_description.Value(), (unsigned long)hostnames.size(), ipstr); } } } } if( !determined_by_parent && (mask&allow_mask(perm)) ) { // In case we are allowing because of not matching a DENY // entry that the user expected us to match (e.g. because // of typo or DNS problem), record all the hostnames we // searched for. if( allow_reason && !peer_description.IsEmpty() ) { allow_reason->sprintf_cat( "; identifiers used for this remote host: %s", peer_description.Value()); } } // finally, add the mask we computed into the table with this IP addr add_hash_entry(sin6_addr, who, mask); } // end of if find_match is FALSE // decode the mask and return True or False to the user. if ( mask & deny_mask(perm) ) { return USER_AUTH_FAILURE; } if ( mask & allow_mask(perm) ) { return USER_AUTH_SUCCESS; } return USER_AUTH_FAILURE; }