📄 auth.c
字号:
/* * Read client's preferred authentication type (protocol 3.7t/3.8t). */voidrfbProcessClientAuthType(cl) rfbClientPtr cl;{ CARD32 auth_type; int n, i; /* Read authentication type selected by the client. */ n = ReadExact(cl->sock, (char *)&auth_type, sizeof(auth_type)); if (n <= 0) { if (n == 0) rfbLog("rfbProcessClientAuthType: client gone\n"); else rfbLogPerror("rfbProcessClientAuthType: read"); rfbCloseSock(cl->sock); return; } auth_type = Swap32IfLE(auth_type); /* Make sure it was present in the list sent by the server. */ for (i = 0; i < cl->nAuthCaps; i++) { if (auth_type == cl->authCaps[i]) break; } if (i >= cl->nAuthCaps) { rfbLog("rfbProcessClientAuthType: " "wrong authentication type requested\n"); rfbCloseSock(cl->sock); return; } switch (auth_type) { case rfbAuthNone: /* Dispatch client input to rfbProcessClientInitMessage. */ cl->state = RFB_INITIALISATION; break; case rfbAuthVNC: rfbVncAuthSendChallenge(cl); break; default: rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); rfbCloseSock(cl->sock); }}/* * Send the authentication challenge. */static voidrfbVncAuthSendChallenge(cl) rfbClientPtr cl;{ vncRandomBytes(cl->authChallenge); if (WriteExact(cl->sock, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { rfbLogPerror("rfbVncAuthSendChallenge: write"); rfbCloseSock(cl->sock); return; } /* Dispatch client input to rfbVncAuthProcessResponse. */ cl->state = RFB_AUTHENTICATION;}/* * rfbVncAuthProcessResponse is called when the client sends its * authentication response. */voidrfbVncAuthProcessResponse(cl) rfbClientPtr cl;{ char passwdFullControl[9]; char passwdViewOnly[9]; int numPasswords; Bool ok; int n; CARD8 encryptedChallenge1[CHALLENGESIZE]; CARD8 encryptedChallenge2[CHALLENGESIZE]; CARD8 response[CHALLENGESIZE]; n = ReadExact(cl->sock, (char *)response, CHALLENGESIZE); if (n <= 0) { if (n != 0) rfbLogPerror("rfbVncAuthProcessResponse: read"); rfbCloseSock(cl->sock); return; } numPasswords = vncDecryptPasswdFromFile2(rfbAuthPasswdFile, passwdFullControl, passwdViewOnly); if (numPasswords == 0) { rfbLog("rfbVncAuthProcessResponse: could not get password from %s\n", rfbAuthPasswdFile); rfbClientAuthFailed(cl, "The server is not configured properly"); return; } memcpy(encryptedChallenge1, cl->authChallenge, CHALLENGESIZE); vncEncryptBytes(encryptedChallenge1, passwdFullControl); memcpy(encryptedChallenge2, cl->authChallenge, CHALLENGESIZE); vncEncryptBytes(encryptedChallenge2, (numPasswords == 2) ? passwdViewOnly : passwdFullControl); /* Lose the passwords from memory */ memset(passwdFullControl, 0, 9); memset(passwdViewOnly, 0, 9); ok = FALSE; if (memcmp(encryptedChallenge1, response, CHALLENGESIZE) == 0) { rfbLog("Full-control authentication passed by %s\n", cl->host); ok = TRUE; cl->viewOnly = FALSE; } else if (memcmp(encryptedChallenge2, response, CHALLENGESIZE) == 0) { rfbLog("View-only authentication passed by %s\n", cl->host); ok = TRUE; cl->viewOnly = TRUE; } if (ok) { rfbAuthUnblock(); rfbClientAuthSucceeded(cl, rfbAuthVNC); } else { rfbLog("rfbVncAuthProcessResponse: authentication failed from %s\n", cl->host); if (rfbAuthConsiderBlocking()) { rfbClientAuthFailed(cl, "Authentication failed, too many tries"); } else { rfbClientAuthFailed(cl, "Authentication failed"); } }}/* * rfbClientConnFailed is called when a client connection has failed * before the authentication stage. */voidrfbClientConnFailed(cl, reason) rfbClientPtr cl; char *reason;{ int headerLen, reasonLen; char buf[8]; headerLen = (cl->protocol_minor_ver >= 7) ? 1 : 4; reasonLen = strlen(reason); ((CARD32 *)buf)[0] = 0; ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen); if ( WriteExact(cl->sock, buf, headerLen) < 0 || WriteExact(cl->sock, buf + 4, 4) < 0 || WriteExact(cl->sock, reason, reasonLen) < 0 ) { rfbLogPerror("rfbClientConnFailed: write"); } rfbCloseSock(cl->sock);}/* * rfbClientAuthFailed is called on authentication failure. Sending a * reason string is defined in the RFB protocol 3.8 and above. */voidrfbClientAuthFailed(cl, reason) rfbClientPtr cl; char *reason;{ int reasonLen; char buf[8]; if (cl->protocol_minor_ver < 8) reason = NULL; /* invalidate the pointer */ reasonLen = (reason == NULL) ? 0 : strlen(reason); ((CARD32 *)buf)[0] = Swap32IfLE(rfbAuthFailed); ((CARD32 *)buf)[1] = Swap32IfLE(reasonLen); if (reasonLen == 0) { if (WriteExact(cl->sock, buf, 4) < 0) { rfbLogPerror("rfbClientAuthFailed: write"); } } else { if ( WriteExact(cl->sock, buf, 8) < 0 || WriteExact(cl->sock, reason, reasonLen) < 0 ) { rfbLogPerror("rfbClientAuthFailed: write"); } } rfbCloseSock(cl->sock);}/* * rfbClientAuthSucceeded is called on successful authentication. * It just sends rfbAuthOK and dispatches client input to * rfbProcessClientInitMessage(). However, rfbAuthOK message is * not sent if authentication was not required and the protocol * version is 3.7 or lower. */voidrfbClientAuthSucceeded(cl, authType) rfbClientPtr cl; CARD32 authType;{ CARD32 authResult; if (cl->protocol_minor_ver >= 8 || authType != rfbAuthNone) { authResult = Swap32IfLE(rfbAuthOK); if (WriteExact(cl->sock, (char *)&authResult, 4) < 0) { rfbLogPerror("rfbClientAuthSucceeded: write"); rfbCloseSock(cl->sock); return; } } /* Dispatch client input to rfbProcessClientInitMessage(). */ cl->state = RFB_INITIALISATION;}/********************************************************************* * Functions to prevent too many successive authentication failures. * FIXME: This should be performed separately per each client IP. *//* Maximum authentication failures before blocking connections */#define MAX_AUTH_TRIES 5/* Delay in ms, doubles for each failure over MAX_AUTH_TRIES */#define AUTH_TOO_MANY_BASE_DELAY 10 * 1000static int rfbAuthTries = 0;static Bool rfbAuthTooManyTries = FALSE;static OsTimerPtr timer = NULL;/* * This function should not be called directly, it is called by * setting a timer in rfbAuthConsiderBlocking(). */static CARD32rfbAuthReenable(OsTimerPtr timer, CARD32 now, pointer arg){ rfbAuthTooManyTries = FALSE; return 0;}/* * This function should be called after each authentication failure. * The return value will be true if there was too many failures. */BoolrfbAuthConsiderBlocking(void){ int i; rfbAuthTries++; if (rfbAuthTries >= MAX_AUTH_TRIES) { CARD32 delay = AUTH_TOO_MANY_BASE_DELAY; for (i = MAX_AUTH_TRIES; i < rfbAuthTries; i++) delay *= 2; timer = TimerSet(timer, 0, delay, rfbAuthReenable, NULL); rfbAuthTooManyTries = TRUE; return TRUE; } return FALSE;}/* * This function should be called after successful authentication. * It resets the counter of authentication failures. Note that it's * not necessary to clear the rfbAuthTooManyTries flag as it will be * reset by the timer function. */voidrfbAuthUnblock(void){ rfbAuthTries = 0;}/* * This function should be called before authentication process. * The return value will be true if there was too many authentication * failures, and the server should not allow another try. */BoolrfbAuthIsBlocked(void){ return rfbAuthTooManyTries;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -