As I said earlier, look at interactions. Check your program designed to be sure the interactions are properly constrained. In particular, network accesses should not be scattered throughout the program. They should be in one or a small set of modules, and each of those modules should have appropriate checking code. So if something goes wrong, the module will detect it. That relieves the higher levels to call these modules of the burden of checking the network parameters or conditions. If there's something coming back from the server, the connection is valid. It'll be bumped up to the process directly or to the processes computation unit or storage unit, and you don't have to worry about, well, did the network fail? If on the other hand, the input comes in from the network, and it's invalid for some reason or the connection is dropped or whatever, then the network module would detect that and send up to its caller and notification that there was a problem, and possibly an error code saying what the problem was. That way, the high-level program only has to handle error cases, and the lower layer module analyzing the problem, figuring out what it is in dealing with it. Higher level location also has to handle the input or output comes from or goes to the module. But again, it doesn't have to know anything about the errors that may arise from the connection. That's the modules business. This also leads to the issue of system resources. If you're going to access parts of the system, makes sure that they're protected, and these are done appropriately within, again, modules. The whole issue with modules goes back to a concept that Jim Anderson developed in the early 1970's. It's called the reference monitor. The reference monitor is an abstraction that has three properties, and the property that is most relevant to this is, it's always invoked. Whenever you want to check security of something or do a security operation, it always goes into the reference monitor to be checked for validity. Here we're using well-defined modules instead of reference monitors, but it's the same idea. The reference monitor is other properties that do not lend it to be implemented directly on systems nowadays, at least most systems. But the well-defined modules and the proper handling within the module and the clarity of the interfaces is an example of something that a reference monitor would have. Also, look out for inputs, where the inputs checked. This is particularly critical if the inputs contain instructions. For example, if you have a little language. You want to make darn sure that little languages properly implemented. If the input consists of commands that your program has to run, for example, spawning a subcommand interpreter, or subshell, or what have you, how is the execution of those constraint, especially if the program that's doing the calling, that's taking the commanding giving it to the subshell is privileged? Should the subshell and your program command you issued also be privileged? Maybe yes, maybe no. The other issue is validating identities. How do you know who you are? Or rather, how does the computer know who you are? While this may seem simple, while I authenticated myself when I log in, it brings up a number of questions. For example, what's you group identity, what's your role identity, what's your login identity, or rather, what's your audit identity, and so forth. So there are many different names that you can have in that the computer works with, and you should be able to validate that those are correct. In addition, there may be naming conflicts, for example, two users may have the same name. How do you handle that situation? Or to a website, may have a name that is actually one thing but appears to be another. How do you handle situations like that? How do you handle naming conflicts, is the gist of this. Other things with implementations, I mentioned buffer overflows already, and they also mentioned the use of little languages. The indivisibility problem I mentioned earlier is an example of a race condition. That's a common error. Error handling is probably where most, well, I shouldn't say most but an awful lot of errors occur, because if something goes wrong, you need to handle it. How do you do it? In a privileged program, if an error occurs and you know why that error occurs, or when that error occurs, the were only this set of things that could have gone wrong, then go ahead and try to recover. If you don't know what caused it, figure out how to terminate the program. I mentioned changing privileges and also, any use of cryptography, both in the implementation and in what you're using it for. Other issues, improper use of library functions. We'll talk about that beautiful one in Course three, but in general, be sure the library functions do what you want. This also goes for other programs when your program depends upon them. When you get things from the environment, from the registry, or from environment variables, that's really a form of input. So check your input. Again, in Course three, we'll show you a situation where you get information from an environment variable, and in a particular construct, that allows you to break into the system, because the environment variable is not properly handled. There are a bunch of other things as well. There are somewhat language-specific or system-specific. For example, Linux. If you have a two environment variables with the same name and different values, and yes, that can happen. Which one gets used? We'll talk about that in Course three. Also, when you write your program, type checking. How do you handle unsigned, how do you handle signed, and so forth. Is this function being called with signed or an unsigned number? Is this function being called with an integer or a real? That sort of thing. Parameter type mismatches are very common error, and I already mentioned the policies and procedures. But this next slide, policies and procedures serves as a good refresher, either ignore them, and do as much checking as you can, or take them into consideration. All right. Let's give you a little thought exercise. I am told that my system is never to be connected to the Internet, either through a wire or wireless. What is some of the assumptions here? What steps would you take to be sure that procedures are followed? What might happen if they aren't? The latter depends a lot upon the environment, of course, as does the second. But if you think about that one, I'll give you a minute or so, and then we'll talk a little bit about some of the assumptions. All right. There are a couple of assumptions in that. The first one, is that the assumption, is that the system will never be connected to the Internet. So one assumption is, while there may be networking components in the system, but they'll never be used. So that's one assumption I would look at. In particular, one of the other assumptions, is that you'll be able to tell whether or not it's connected to the Internet. If it's through a wire, then you can unplug it. But what about wireless? As far as the procedures go, one other assumption up there, it's never to be connected to the Internet. What about the local networks? Can it be connected to a local network that's not connected to the Internet? If so, how do you know that local network is not connected to the Internet, and so forth. The easiest way incidentally to make sure this policy is followed, it's simply to remove all networking hardware from the system. If you don't have a wireless card, you can't turn it on. If you don't have ethernet cards or networking cards, you can't connect to a network. That solves the problem right there. Let's go on to the next. For that one, I should add also, you'll have to be careful if people put in USB sticks with wireless on them. So it's also a good idea to remove all networking software as well. So even if they do put something like that in, they won't be able to use it.