Your problem is this bit:
for(byte i=card_no*5;i<(card_no*5)+5;i++){
crd_buf[i] = rfid.serNum[i];}
For the first card you're copying bytes 0-4 of the serNum to bytes 0-4 of crd_buf.
However for the second card you're copying bytes 5-9 of serNum to bytes 5-9 of crd_buf. That's correct for crd_buf but wrong for serNum.
The right way would be to add card_no*5 to i when creating the index:
for(byte i=0; i<5; i++){
crd_buf[(card_no*5) + i] = rfid.serNum[i];}
Or better to define your card buffer as a 2D array so you don't need to do that calculation:
byte crd_buf[CARDS][5];
for (i = 0; i < 5; i++) {
crd_buf[card_no][i] = rfid.serNum[i];
}
Or simpler:
memcpy(crd_buf[card_no], rfid.serNum, 5);
For your second question, don't print your message at all in the loop.
Instead start out assuming that access is denied. Then if a card matches, grant access. The simplest way is with a flag.
if (rfid.readCardSerial()){
bool accessGranted = false; // A flag to store the state - start off denied.
for(byte i=0;i<card_no;i++){
if(!memcmp(crd_buf+(i*5),rfid.serNum,5)){
accessGranted = true;
}
}
// replace these with your own message routines.
if (accessGranted) {
Serial.println("Access Granted");
} else {
Serial.println("Access Denied");
}
}